blob: bf9a17e585ed9414f8e24818f79b35c22399167c [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
Jamie Madillf75ab352015-03-16 10:46:52 -040021namespace
22{
23
24ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
25{
26 ClearParameters clearParams;
27 memset(&clearParams, 0, sizeof(ClearParameters));
28
29 const auto &blendState = state.getBlendState();
30
31 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
32 {
33 clearParams.clearColor[i] = false;
34 }
35 clearParams.colorFClearValue = state.getColorClearValue();
36 clearParams.colorClearType = GL_FLOAT;
37 clearParams.colorMaskRed = blendState.colorMaskRed;
38 clearParams.colorMaskGreen = blendState.colorMaskGreen;
39 clearParams.colorMaskBlue = blendState.colorMaskBlue;
40 clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
41 clearParams.clearDepth = false;
42 clearParams.depthClearValue = state.getDepthClearValue();
43 clearParams.clearStencil = false;
44 clearParams.stencilClearValue = state.getStencilClearValue();
45 clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
46 clearParams.scissorEnabled = state.isScissorTestEnabled();
47 clearParams.scissor = state.getScissor();
48
49 const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
50 if (mask & GL_COLOR_BUFFER_BIT)
51 {
52 if (framebufferObject->hasEnabledColorAttachment())
53 {
54 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
55 {
56 clearParams.clearColor[i] = true;
57 }
58 }
59 }
60
61 if (mask & GL_DEPTH_BUFFER_BIT)
62 {
63 if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
64 {
65 clearParams.clearDepth = true;
66 }
67 }
68
69 if (mask & GL_STENCIL_BUFFER_BIT)
70 {
71 if (framebufferObject->getStencilbuffer() != NULL &&
72 framebufferObject->getStencilbuffer()->getStencilSize() > 0)
73 {
74 clearParams.clearStencil = true;
75 }
76 }
77
78 return clearParams;
79}
80
81}
82
Geoff Langc2e75af2015-01-05 14:26:24 -050083DefaultAttachmentD3D::DefaultAttachmentD3D(RenderTargetD3D *renderTarget)
Geoff Lang6a1e6b92014-11-06 10:42:45 -050084 : mRenderTarget(renderTarget)
85{
86 ASSERT(mRenderTarget);
87}
88
89DefaultAttachmentD3D::~DefaultAttachmentD3D()
90{
91 SafeDelete(mRenderTarget);
92}
93
94DefaultAttachmentD3D *DefaultAttachmentD3D::makeDefaultAttachmentD3D(DefaultAttachmentImpl* impl)
95{
96 ASSERT(HAS_DYNAMIC_TYPE(DefaultAttachmentD3D*, impl));
97 return static_cast<DefaultAttachmentD3D*>(impl);
98}
99
100GLsizei DefaultAttachmentD3D::getWidth() const
101{
102 return mRenderTarget->getWidth();
103}
104
105GLsizei DefaultAttachmentD3D::getHeight() const
106{
107 return mRenderTarget->getHeight();
108}
109
110GLenum DefaultAttachmentD3D::getInternalFormat() const
111{
112 return mRenderTarget->getInternalFormat();
113}
114
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500115GLsizei DefaultAttachmentD3D::getSamples() const
116{
117 return mRenderTarget->getSamples();
118}
119
Geoff Langc2e75af2015-01-05 14:26:24 -0500120RenderTargetD3D *DefaultAttachmentD3D::getRenderTarget() const
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500121{
122 return mRenderTarget;
123}
124
Jamie Madilld1405e52015-03-05 15:41:39 -0500125FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
126 : FramebufferImpl(data),
127 mRenderer(renderer),
Jamie Madill85a18042015-03-05 15:41:41 -0500128 mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr),
129 mInvalidateColorAttachmentCache(true)
Geoff Langda88add2014-12-01 10:22:01 -0500130{
131 ASSERT(mRenderer != nullptr);
132}
133
134FramebufferD3D::~FramebufferD3D()
135{
136}
137
Jamie Madill7147f012015-03-05 15:41:40 -0500138void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500139{
Jamie Madill85a18042015-03-05 15:41:41 -0500140 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500141}
142
Jamie Madillf90353e2015-03-05 19:37:58 -0500143void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500144{
145}
146
Jamie Madill7147f012015-03-05 15:41:40 -0500147void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500148{
149}
150
Jamie Madill7147f012015-03-05 15:41:40 -0500151void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500152{
153}
154
Jamie Madill7147f012015-03-05 15:41:40 -0500155void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500156{
Jamie Madill85a18042015-03-05 15:41:41 -0500157 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500158}
159
Jamie Madill7147f012015-03-05 15:41:40 -0500160void FramebufferD3D::setReadBuffer(GLenum)
Geoff Lang9dd95802014-12-01 11:12:59 -0500161{
162}
163
Geoff Langb04dc822014-12-01 12:02:02 -0500164gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
165{
Jamie Madillf75ab352015-03-16 10:46:52 -0400166 ClearParameters clearParams = GetClearParameters(state, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500167 return clear(state, clearParams);
168}
169
170gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
171{
172 // glClearBufferfv can be called to clear the color buffer or depth buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400173 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500174
175 if (buffer == GL_COLOR)
176 {
177 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
178 {
179 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
180 }
181 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
182 clearParams.colorClearType = GL_FLOAT;
183 }
184
185 if (buffer == GL_DEPTH)
186 {
187 clearParams.clearDepth = true;
188 clearParams.depthClearValue = values[0];
189 }
190
191 return clear(state, clearParams);
192}
193
194gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
195{
196 // glClearBufferuiv can only be called to clear a color buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400197 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500198 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
199 {
200 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
201 }
202 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
203 clearParams.colorClearType = GL_UNSIGNED_INT;
204
205 return clear(state, clearParams);
206}
207
208gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
209{
210 // glClearBufferiv can be called to clear the color buffer or stencil buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400211 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500212
213 if (buffer == GL_COLOR)
214 {
215 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
216 {
217 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
218 }
219 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
220 clearParams.colorClearType = GL_INT;
221 }
222
223 if (buffer == GL_STENCIL)
224 {
225 clearParams.clearStencil = true;
226 clearParams.stencilClearValue = values[1];
227 }
228
229 return clear(state, clearParams);
230}
231
232gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
233{
234 // glClearBufferfi can only be called to clear a depth stencil buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400235 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500236 clearParams.clearDepth = true;
237 clearParams.depthClearValue = depth;
238 clearParams.clearStencil = true;
239 clearParams.stencilClearValue = stencil;
240
241 return clear(state, clearParams);
242}
243
Geoff Langbce529e2014-12-01 12:48:41 -0500244GLenum FramebufferD3D::getImplementationColorReadFormat() const
245{
Jamie Madill7147f012015-03-05 15:41:40 -0500246 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500247
Jamie Madillb885e572015-02-03 16:16:04 -0500248 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500249 {
250 return GL_NONE;
251 }
252
Geoff Langc2e75af2015-01-05 14:26:24 -0500253 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500254 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500255 if (error.isError())
256 {
257 return GL_NONE;
258 }
Geoff Langbce529e2014-12-01 12:48:41 -0500259
Geoff Langd8a22582014-12-17 15:28:23 -0500260 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
261 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
262
263 return implementationFormatInfo.format;
Geoff Langbce529e2014-12-01 12:48:41 -0500264}
265
266GLenum FramebufferD3D::getImplementationColorReadType() const
267{
Jamie Madill7147f012015-03-05 15:41:40 -0500268 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500269
Jamie Madillb885e572015-02-03 16:16:04 -0500270 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500271 {
272 return GL_NONE;
273 }
274
Geoff Langc2e75af2015-01-05 14:26:24 -0500275 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500276 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500277 if (error.isError())
278 {
279 return GL_NONE;
280 }
Geoff Langbce529e2014-12-01 12:48:41 -0500281
Geoff Langd8a22582014-12-17 15:28:23 -0500282 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
283 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
284
285 return implementationFormatInfo.type;
Geoff Langbce529e2014-12-01 12:48:41 -0500286}
287
288gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
289{
Jamie Madill87de3622015-03-16 10:41:44 -0400290 const gl::PixelPackState &packState = state.getPackState();
291
292 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
293 {
294 UNIMPLEMENTED();
295 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
296 }
297
Geoff Langbce529e2014-12-01 12:48:41 -0500298 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
299 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Jamie Madill87de3622015-03-16 10:41:44 -0400300 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0);
Geoff Langbce529e2014-12-01 12:48:41 -0500301
Jamie Madill87de3622015-03-16 10:41:44 -0400302 return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels));
Geoff Langbce529e2014-12-01 12:48:41 -0500303}
304
Geoff Lang54bd5a42014-12-01 12:51:04 -0500305gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
306 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
307{
308 bool blitRenderTarget = false;
309 if ((mask & GL_COLOR_BUFFER_BIT) &&
310 sourceFramebuffer->getReadColorbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500311 mData.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500312 {
313 blitRenderTarget = true;
314 }
315
316 bool blitStencil = false;
317 if ((mask & GL_STENCIL_BUFFER_BIT) &&
318 sourceFramebuffer->getStencilbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500319 mData.mStencilAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500320 {
321 blitStencil = true;
322 }
323
324 bool blitDepth = false;
325 if ((mask & GL_DEPTH_BUFFER_BIT) &&
326 sourceFramebuffer->getDepthbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500327 mData.mDepthAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500328 {
329 blitDepth = true;
330 }
331
332 if (blitRenderTarget || blitDepth || blitStencil)
333 {
334 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
335 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
336 filter, sourceFramebuffer);
337 if (error.isError())
338 {
339 return error;
340 }
341 }
342
343 return gl::Error(GL_NO_ERROR);
344}
345
Geoff Lang748f74e2014-12-01 11:25:34 -0500346GLenum FramebufferD3D::checkStatus() const
347{
348 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madill7147f012015-03-05 15:41:40 -0500349 for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500350 {
Jamie Madill7147f012015-03-05 15:41:40 -0500351 const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500352 if (attachment != nullptr)
353 {
354 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
355 {
Jamie Madill7147f012015-03-05 15:41:40 -0500356 const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500357 if (prevAttachment != nullptr &&
358 (attachment->id() == prevAttachment->id() &&
359 attachment->type() == prevAttachment->type()))
360 {
361 return GL_FRAMEBUFFER_UNSUPPORTED;
362 }
363 }
364 }
365 }
366
367 return GL_FRAMEBUFFER_COMPLETE;
368}
369
Jamie Madill7147f012015-03-05 15:41:40 -0500370const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const
371{
Jamie Madill85a18042015-03-05 15:41:41 -0500372 if (!workarounds.mrtPerfWorkaround)
373 {
374 return mData.mColorAttachments;
375 }
376
377 if (!mInvalidateColorAttachmentCache)
378 {
379 return mColorAttachmentsForRender;
380 }
381
Jamie Madill7147f012015-03-05 15:41:40 -0500382 // Does not actually free memory
383 mColorAttachmentsForRender.clear();
384
385 for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex)
386 {
387 GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex];
388 gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex];
389
390 if (colorAttachment != nullptr && drawBufferState != GL_NONE)
391 {
392 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
393 mColorAttachmentsForRender.push_back(colorAttachment);
394 }
Jamie Madill7147f012015-03-05 15:41:40 -0500395 }
396
Jamie Madill85a18042015-03-05 15:41:41 -0500397 mInvalidateColorAttachmentCache = false;
Jamie Madill7147f012015-03-05 15:41:40 -0500398 return mColorAttachmentsForRender;
399}
400
Geoff Langc2e75af2015-01-05 14:26:24 -0500401gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT)
Geoff Langb5d8f232014-12-04 15:43:01 -0500402{
403 if (attachment->type() == GL_TEXTURE)
404 {
405 gl::Texture *texture = attachment->getTexture();
406 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500407 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500408 const gl::ImageIndex *index = attachment->getTextureImageIndex();
409 ASSERT(index);
410 return textureD3D->getRenderTarget(*index, outRT);
411 }
412 else if (attachment->type() == GL_RENDERBUFFER)
413 {
414 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
415 ASSERT(renderbuffer);
416 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
417 *outRT = renderbufferD3D->getRenderTarget();
418 return gl::Error(GL_NO_ERROR);
419 }
420 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
421 {
422 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
423 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
424 ASSERT(defaultAttachmentD3D);
425
426 *outRT = defaultAttachmentD3D->getRenderTarget();
427 return gl::Error(GL_NO_ERROR);
428 }
429 else
430 {
431 UNREACHABLE();
432 return gl::Error(GL_INVALID_OPERATION);
433 }
434}
435
436// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
437unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
438{
439 if (attachment->type() == GL_TEXTURE)
440 {
441 gl::Texture *texture = attachment->getTexture();
442 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500443 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500444 const gl::ImageIndex *index = attachment->getTextureImageIndex();
445 ASSERT(index);
446 return textureD3D->getRenderTargetSerial(*index);
447 }
448 else if (attachment->type() == GL_RENDERBUFFER)
449 {
450 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
451 ASSERT(renderbuffer);
452 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
453 return renderbufferD3D->getRenderTargetSerial();
454 }
455 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
456 {
457 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
458 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
459 ASSERT(defaultAttachmentD3D);
460 return defaultAttachmentD3D->getRenderTarget()->getSerial();
461 }
462 else
463 {
464 UNREACHABLE();
465 return 0;
466 }
467}
468
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500469}