blob: 620b14a55aaa8c63f377713c5b60e4f6ce9f09dd [file] [log] [blame]
Geoff Lang6a1e6b92014-11-06 10:42:45 -05001//
2// Copyright 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Geoff Langda88add2014-12-01 10:22:01 -05007// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes.
Geoff Lang6a1e6b92014-11-06 10:42:45 -05008
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050010#include "libANGLE/renderer/d3d/TextureD3D.h"
Geoff Langda88add2014-12-01 10:22:01 -050011#include "libANGLE/renderer/d3d/RendererD3D.h"
Geoff Langc2e75af2015-01-05 14:26:24 -050012#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050013#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
Geoff Langbce529e2014-12-01 12:48:41 -050014#include "libANGLE/formatutils.h"
Geoff Lang54bd5a42014-12-01 12:51:04 -050015#include "libANGLE/Framebuffer.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050016#include "libANGLE/FramebufferAttachment.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050017
18namespace rx
19{
20
Geoff Langc2e75af2015-01-05 14:26:24 -050021DefaultAttachmentD3D::DefaultAttachmentD3D(RenderTargetD3D *renderTarget)
Geoff Lang6a1e6b92014-11-06 10:42:45 -050022 : mRenderTarget(renderTarget)
23{
24 ASSERT(mRenderTarget);
25}
26
27DefaultAttachmentD3D::~DefaultAttachmentD3D()
28{
29 SafeDelete(mRenderTarget);
30}
31
32DefaultAttachmentD3D *DefaultAttachmentD3D::makeDefaultAttachmentD3D(DefaultAttachmentImpl* impl)
33{
34 ASSERT(HAS_DYNAMIC_TYPE(DefaultAttachmentD3D*, impl));
35 return static_cast<DefaultAttachmentD3D*>(impl);
36}
37
38GLsizei DefaultAttachmentD3D::getWidth() const
39{
40 return mRenderTarget->getWidth();
41}
42
43GLsizei DefaultAttachmentD3D::getHeight() const
44{
45 return mRenderTarget->getHeight();
46}
47
48GLenum DefaultAttachmentD3D::getInternalFormat() const
49{
50 return mRenderTarget->getInternalFormat();
51}
52
Geoff Lang6a1e6b92014-11-06 10:42:45 -050053GLsizei DefaultAttachmentD3D::getSamples() const
54{
55 return mRenderTarget->getSamples();
56}
57
Geoff Langc2e75af2015-01-05 14:26:24 -050058RenderTargetD3D *DefaultAttachmentD3D::getRenderTarget() const
Geoff Lang6a1e6b92014-11-06 10:42:45 -050059{
60 return mRenderTarget;
61}
62
Jamie Madilld1405e52015-03-05 15:41:39 -050063FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
64 : FramebufferImpl(data),
65 mRenderer(renderer),
Jamie Madill7147f012015-03-05 15:41:40 -050066 mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr)
Geoff Langda88add2014-12-01 10:22:01 -050067{
68 ASSERT(mRenderer != nullptr);
69}
70
71FramebufferD3D::~FramebufferD3D()
72{
73}
74
Jamie Madill7147f012015-03-05 15:41:40 -050075void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050076{
77}
78
Jamie Madill7147f012015-03-05 15:41:40 -050079void FramebufferD3D::setDepthttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050080{
81}
82
Jamie Madill7147f012015-03-05 15:41:40 -050083void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050084{
85}
86
Jamie Madill7147f012015-03-05 15:41:40 -050087void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050088{
89}
90
Jamie Madill7147f012015-03-05 15:41:40 -050091void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
Geoff Lang9dd95802014-12-01 11:12:59 -050092{
93}
94
Jamie Madill7147f012015-03-05 15:41:40 -050095void FramebufferD3D::setReadBuffer(GLenum)
Geoff Lang9dd95802014-12-01 11:12:59 -050096{
97}
98
Geoff Lang9ad4bda2014-12-01 11:03:09 -050099gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
100{
101 // No-op in D3D
102 return gl::Error(GL_NO_ERROR);
103}
104
105gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
106{
107 // No-op in D3D
108 return gl::Error(GL_NO_ERROR);
109}
110
Geoff Langb04dc822014-12-01 12:02:02 -0500111gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
112{
113 gl::ClearParameters clearParams = state.getClearParameters(mask);
114 return clear(state, clearParams);
115}
116
117gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
118{
119 // glClearBufferfv can be called to clear the color buffer or depth buffer
120 gl::ClearParameters clearParams = state.getClearParameters(0);
121
122 if (buffer == GL_COLOR)
123 {
124 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
125 {
126 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
127 }
128 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
129 clearParams.colorClearType = GL_FLOAT;
130 }
131
132 if (buffer == GL_DEPTH)
133 {
134 clearParams.clearDepth = true;
135 clearParams.depthClearValue = values[0];
136 }
137
138 return clear(state, clearParams);
139}
140
141gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
142{
143 // glClearBufferuiv can only be called to clear a color buffer
144 gl::ClearParameters clearParams = state.getClearParameters(0);
145 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
146 {
147 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
148 }
149 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
150 clearParams.colorClearType = GL_UNSIGNED_INT;
151
152 return clear(state, clearParams);
153}
154
155gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
156{
157 // glClearBufferiv can be called to clear the color buffer or stencil buffer
158 gl::ClearParameters clearParams = state.getClearParameters(0);
159
160 if (buffer == GL_COLOR)
161 {
162 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
163 {
164 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
165 }
166 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
167 clearParams.colorClearType = GL_INT;
168 }
169
170 if (buffer == GL_STENCIL)
171 {
172 clearParams.clearStencil = true;
173 clearParams.stencilClearValue = values[1];
174 }
175
176 return clear(state, clearParams);
177}
178
179gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
180{
181 // glClearBufferfi can only be called to clear a depth stencil buffer
182 gl::ClearParameters clearParams = state.getClearParameters(0);
183 clearParams.clearDepth = true;
184 clearParams.depthClearValue = depth;
185 clearParams.clearStencil = true;
186 clearParams.stencilClearValue = stencil;
187
188 return clear(state, clearParams);
189}
190
Geoff Langbce529e2014-12-01 12:48:41 -0500191GLenum FramebufferD3D::getImplementationColorReadFormat() const
192{
Jamie Madill7147f012015-03-05 15:41:40 -0500193 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500194
Jamie Madillb885e572015-02-03 16:16:04 -0500195 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500196 {
197 return GL_NONE;
198 }
199
Geoff Langc2e75af2015-01-05 14:26:24 -0500200 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500201 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500202 if (error.isError())
203 {
204 return GL_NONE;
205 }
Geoff Langbce529e2014-12-01 12:48:41 -0500206
Geoff Langd8a22582014-12-17 15:28:23 -0500207 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
208 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
209
210 return implementationFormatInfo.format;
Geoff Langbce529e2014-12-01 12:48:41 -0500211}
212
213GLenum FramebufferD3D::getImplementationColorReadType() const
214{
Jamie Madill7147f012015-03-05 15:41:40 -0500215 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500216
Jamie Madillb885e572015-02-03 16:16:04 -0500217 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500218 {
219 return GL_NONE;
220 }
221
Geoff Langc2e75af2015-01-05 14:26:24 -0500222 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500223 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500224 if (error.isError())
225 {
226 return GL_NONE;
227 }
Geoff Langbce529e2014-12-01 12:48:41 -0500228
Geoff Langd8a22582014-12-17 15:28:23 -0500229 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
230 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
231
232 return implementationFormatInfo.type;
Geoff Langbce529e2014-12-01 12:48:41 -0500233}
234
235gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
236{
237 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
238 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Minmin Gongb8aee3b2015-01-27 14:42:36 -0800239 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment(), 0);
Geoff Langbce529e2014-12-01 12:48:41 -0500240
241 return readPixels(area, format, type, outputPitch, state.getPackState(), reinterpret_cast<uint8_t*>(pixels));
242}
243
Geoff Lang54bd5a42014-12-01 12:51:04 -0500244gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
245 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
246{
247 bool blitRenderTarget = false;
248 if ((mask & GL_COLOR_BUFFER_BIT) &&
249 sourceFramebuffer->getReadColorbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500250 mData.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500251 {
252 blitRenderTarget = true;
253 }
254
255 bool blitStencil = false;
256 if ((mask & GL_STENCIL_BUFFER_BIT) &&
257 sourceFramebuffer->getStencilbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500258 mData.mStencilAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500259 {
260 blitStencil = true;
261 }
262
263 bool blitDepth = false;
264 if ((mask & GL_DEPTH_BUFFER_BIT) &&
265 sourceFramebuffer->getDepthbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500266 mData.mDepthAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500267 {
268 blitDepth = true;
269 }
270
271 if (blitRenderTarget || blitDepth || blitStencil)
272 {
273 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
274 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
275 filter, sourceFramebuffer);
276 if (error.isError())
277 {
278 return error;
279 }
280 }
281
282 return gl::Error(GL_NO_ERROR);
283}
284
Geoff Lang748f74e2014-12-01 11:25:34 -0500285GLenum FramebufferD3D::checkStatus() const
286{
287 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madill7147f012015-03-05 15:41:40 -0500288 for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500289 {
Jamie Madill7147f012015-03-05 15:41:40 -0500290 const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500291 if (attachment != nullptr)
292 {
293 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
294 {
Jamie Madill7147f012015-03-05 15:41:40 -0500295 const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500296 if (prevAttachment != nullptr &&
297 (attachment->id() == prevAttachment->id() &&
298 attachment->type() == prevAttachment->type()))
299 {
300 return GL_FRAMEBUFFER_UNSUPPORTED;
301 }
302 }
303 }
304 }
305
306 return GL_FRAMEBUFFER_COMPLETE;
307}
308
Jamie Madill7147f012015-03-05 15:41:40 -0500309const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const
310{
311 // Does not actually free memory
312 mColorAttachmentsForRender.clear();
313
314 for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex)
315 {
316 GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex];
317 gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex];
318
319 if (colorAttachment != nullptr && drawBufferState != GL_NONE)
320 {
321 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
322 mColorAttachmentsForRender.push_back(colorAttachment);
323 }
324 else if (!workarounds.mrtPerfWorkaround)
325 {
326 mColorAttachmentsForRender.push_back(nullptr);
327 }
328 }
329
330 return mColorAttachmentsForRender;
331}
332
Geoff Langc2e75af2015-01-05 14:26:24 -0500333gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT)
Geoff Langb5d8f232014-12-04 15:43:01 -0500334{
335 if (attachment->type() == GL_TEXTURE)
336 {
337 gl::Texture *texture = attachment->getTexture();
338 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500339 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500340 const gl::ImageIndex *index = attachment->getTextureImageIndex();
341 ASSERT(index);
342 return textureD3D->getRenderTarget(*index, outRT);
343 }
344 else if (attachment->type() == GL_RENDERBUFFER)
345 {
346 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
347 ASSERT(renderbuffer);
348 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
349 *outRT = renderbufferD3D->getRenderTarget();
350 return gl::Error(GL_NO_ERROR);
351 }
352 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
353 {
354 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
355 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
356 ASSERT(defaultAttachmentD3D);
357
358 *outRT = defaultAttachmentD3D->getRenderTarget();
359 return gl::Error(GL_NO_ERROR);
360 }
361 else
362 {
363 UNREACHABLE();
364 return gl::Error(GL_INVALID_OPERATION);
365 }
366}
367
368// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
369unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
370{
371 if (attachment->type() == GL_TEXTURE)
372 {
373 gl::Texture *texture = attachment->getTexture();
374 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500375 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500376 const gl::ImageIndex *index = attachment->getTextureImageIndex();
377 ASSERT(index);
378 return textureD3D->getRenderTargetSerial(*index);
379 }
380 else if (attachment->type() == GL_RENDERBUFFER)
381 {
382 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
383 ASSERT(renderbuffer);
384 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
385 return renderbufferD3D->getRenderTargetSerial();
386 }
387 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
388 {
389 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
390 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
391 ASSERT(defaultAttachmentD3D);
392 return defaultAttachmentD3D->getRenderTarget()->getSerial();
393 }
394 else
395 {
396 UNREACHABLE();
397 return 0;
398 }
399}
400
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500401}