blob: b443f9a246f58908343283ab2fd58a7955dd6def [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"
Jamie Madillc46f45d2015-03-31 13:20:55 -040010
Jamie Madill20e005b2017-04-07 14:19:22 -040011#include "common/bitset_utils.h"
Jamie Madillc564c072017-06-01 12:45:42 -040012#include "libANGLE/Context.h"
Geoff Lang54bd5a42014-12-01 12:51:04 -050013#include "libANGLE/Framebuffer.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050014#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040015#include "libANGLE/Surface.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040016#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040017#include "libANGLE/renderer/ContextImpl.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040018#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040019#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
20#include "libANGLE/renderer/d3d/RendererD3D.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040021#include "libANGLE/renderer/d3d/SurfaceD3D.h"
22#include "libANGLE/renderer/d3d/SwapChainD3D.h"
23#include "libANGLE/renderer/d3d/TextureD3D.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050024
25namespace rx
26{
27
Jamie Madillf75ab352015-03-16 10:46:52 -040028namespace
29{
30
31ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
32{
33 ClearParameters clearParams;
34 memset(&clearParams, 0, sizeof(ClearParameters));
35
36 const auto &blendState = state.getBlendState();
37
38 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
39 {
40 clearParams.clearColor[i] = false;
41 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -080042 clearParams.colorF = state.getColorClearValue();
43 clearParams.colorType = GL_FLOAT;
44 clearParams.colorMaskRed = blendState.colorMaskRed;
45 clearParams.colorMaskGreen = blendState.colorMaskGreen;
46 clearParams.colorMaskBlue = blendState.colorMaskBlue;
47 clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
48 clearParams.clearDepth = false;
49 clearParams.depthValue = state.getDepthClearValue();
50 clearParams.clearStencil = false;
51 clearParams.stencilValue = state.getStencilClearValue();
Jamie Madillf75ab352015-03-16 10:46:52 -040052 clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
Shahmeer Esmail5416f752017-03-09 22:02:43 -080053 clearParams.scissorEnabled = state.isScissorTestEnabled();
54 clearParams.scissor = state.getScissor();
Jamie Madillf75ab352015-03-16 10:46:52 -040055
56 const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
57 if (mask & GL_COLOR_BUFFER_BIT)
58 {
Geoff Langa15472a2015-08-11 11:48:03 -040059 if (framebufferObject->hasEnabledDrawBuffer())
Jamie Madillf75ab352015-03-16 10:46:52 -040060 {
61 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
62 {
63 clearParams.clearColor[i] = true;
64 }
65 }
66 }
67
68 if (mask & GL_DEPTH_BUFFER_BIT)
69 {
Yunchao He4f285442017-04-21 12:15:49 +080070 if (state.getDepthStencilState().depthMask &&
71 framebufferObject->getDepthbuffer() != nullptr)
Jamie Madillf75ab352015-03-16 10:46:52 -040072 {
73 clearParams.clearDepth = true;
74 }
75 }
76
77 if (mask & GL_STENCIL_BUFFER_BIT)
78 {
Yunchao He4f285442017-04-21 12:15:49 +080079 if (framebufferObject->getStencilbuffer() != nullptr &&
Jamie Madillf75ab352015-03-16 10:46:52 -040080 framebufferObject->getStencilbuffer()->getStencilSize() > 0)
81 {
82 clearParams.clearStencil = true;
83 }
84 }
85
86 return clearParams;
87}
Jamie Madillf75ab352015-03-16 10:46:52 -040088}
89
Jamie Madillacf2f3a2017-11-21 19:22:44 -050090ClearParameters::ClearParameters() = default;
91
92ClearParameters::ClearParameters(const ClearParameters &other) = default;
93
Jamie Madill48ef11b2016-04-27 15:21:52 -040094FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
JiangYizhou10d41392017-12-18 18:13:36 +080095 : FramebufferImpl(data), mRenderer(renderer), mDummyAttachment()
Geoff Langda88add2014-12-01 10:22:01 -050096{
Geoff Langda88add2014-12-01 10:22:01 -050097}
98
99FramebufferD3D::~FramebufferD3D()
100{
101}
102
Jamie Madillc564c072017-06-01 12:45:42 -0400103gl::Error FramebufferD3D::clear(const gl::Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500104{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700105 ClearParameters clearParams = GetClearParameters(context->getGLState(), mask);
Jamie Madill8415b5f2016-04-26 13:41:39 -0400106 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500107}
108
Jamie Madillc564c072017-06-01 12:45:42 -0400109gl::Error FramebufferD3D::clearBufferfv(const gl::Context *context,
Dian Xiang40281592015-11-19 18:24:44 -0800110 GLenum buffer,
111 GLint drawbuffer,
112 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500113{
114 // glClearBufferfv can be called to clear the color buffer or depth buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700115 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500116
117 if (buffer == GL_COLOR)
118 {
119 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
120 {
121 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
122 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800123 clearParams.colorF = gl::ColorF(values[0], values[1], values[2], values[3]);
124 clearParams.colorType = GL_FLOAT;
Geoff Langb04dc822014-12-01 12:02:02 -0500125 }
126
127 if (buffer == GL_DEPTH)
128 {
129 clearParams.clearDepth = true;
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800130 clearParams.depthValue = values[0];
Geoff Langb04dc822014-12-01 12:02:02 -0500131 }
132
Jamie Madill8415b5f2016-04-26 13:41:39 -0400133 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500134}
135
Jamie Madillc564c072017-06-01 12:45:42 -0400136gl::Error FramebufferD3D::clearBufferuiv(const gl::Context *context,
Dian Xiang40281592015-11-19 18:24:44 -0800137 GLenum buffer,
138 GLint drawbuffer,
139 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500140{
141 // glClearBufferuiv can only be called to clear a color buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700142 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500143 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
144 {
145 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
146 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800147 clearParams.colorUI = gl::ColorUI(values[0], values[1], values[2], values[3]);
148 clearParams.colorType = GL_UNSIGNED_INT;
Geoff Langb04dc822014-12-01 12:02:02 -0500149
Jamie Madill8415b5f2016-04-26 13:41:39 -0400150 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500151}
152
Jamie Madillc564c072017-06-01 12:45:42 -0400153gl::Error FramebufferD3D::clearBufferiv(const gl::Context *context,
Dian Xiang40281592015-11-19 18:24:44 -0800154 GLenum buffer,
155 GLint drawbuffer,
156 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500157{
158 // glClearBufferiv can be called to clear the color buffer or stencil buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700159 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500160
161 if (buffer == GL_COLOR)
162 {
163 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
164 {
165 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
166 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800167 clearParams.colorI = gl::ColorI(values[0], values[1], values[2], values[3]);
168 clearParams.colorType = GL_INT;
Geoff Langb04dc822014-12-01 12:02:02 -0500169 }
170
171 if (buffer == GL_STENCIL)
172 {
173 clearParams.clearStencil = true;
Jamie Madill805d2812017-09-20 13:21:42 -0400174 clearParams.stencilValue = values[0];
Geoff Langb04dc822014-12-01 12:02:02 -0500175 }
176
Jamie Madill8415b5f2016-04-26 13:41:39 -0400177 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500178}
179
Jamie Madillc564c072017-06-01 12:45:42 -0400180gl::Error FramebufferD3D::clearBufferfi(const gl::Context *context,
Dian Xiang40281592015-11-19 18:24:44 -0800181 GLenum buffer,
182 GLint drawbuffer,
183 GLfloat depth,
184 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500185{
186 // glClearBufferfi can only be called to clear a depth stencil buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700187 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800188 clearParams.clearDepth = true;
189 clearParams.depthValue = depth;
190 clearParams.clearStencil = true;
191 clearParams.stencilValue = stencil;
Geoff Langb04dc822014-12-01 12:02:02 -0500192
Jamie Madill8415b5f2016-04-26 13:41:39 -0400193 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500194}
195
Jamie Madill4928b7c2017-06-20 12:57:39 -0400196GLenum FramebufferD3D::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -0500197{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400198 const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500199
Jamie Madillb885e572015-02-03 16:16:04 -0500200 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500201 {
202 return GL_NONE;
203 }
204
Yunchao Hed7297bf2017-04-19 15:27:10 +0800205 RenderTargetD3D *attachmentRenderTarget = nullptr;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400206 gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500207 if (error.isError())
208 {
209 return GL_NONE;
210 }
Geoff Langbce529e2014-12-01 12:48:41 -0500211
Geoff Langd8a22582014-12-17 15:28:23 -0500212 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
Geoff Langca271392017-04-05 12:30:00 -0400213 const gl::InternalFormat &implementationFormatInfo =
214 gl::GetSizedInternalFormatInfo(implementationFormat);
Geoff Langd8a22582014-12-17 15:28:23 -0500215
Geoff Langf607c602016-09-21 11:46:48 -0400216 return implementationFormatInfo.getReadPixelsFormat();
Geoff Langbce529e2014-12-01 12:48:41 -0500217}
218
Jamie Madill4928b7c2017-06-20 12:57:39 -0400219GLenum FramebufferD3D::getImplementationColorReadType(const gl::Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -0500220{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400221 const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500222
Jamie Madillb885e572015-02-03 16:16:04 -0500223 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500224 {
225 return GL_NONE;
226 }
227
Yunchao Hed7297bf2017-04-19 15:27:10 +0800228 RenderTargetD3D *attachmentRenderTarget = nullptr;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400229 gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500230 if (error.isError())
231 {
232 return GL_NONE;
233 }
Geoff Langbce529e2014-12-01 12:48:41 -0500234
Geoff Langd8a22582014-12-17 15:28:23 -0500235 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
Geoff Langca271392017-04-05 12:30:00 -0400236 const gl::InternalFormat &implementationFormatInfo =
237 gl::GetSizedInternalFormatInfo(implementationFormat);
Geoff Langd8a22582014-12-17 15:28:23 -0500238
Geoff Langc71ea662017-09-26 17:06:02 -0400239 return implementationFormatInfo.getReadPixelsType(context->getClientVersion());
Geoff Langbce529e2014-12-01 12:48:41 -0500240}
241
Jamie Madillc564c072017-06-01 12:45:42 -0400242gl::Error FramebufferD3D::readPixels(const gl::Context *context,
Frank Henigman739bd8b2017-06-19 21:02:27 -0400243 const gl::Rectangle &origArea,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400244 GLenum format,
245 GLenum type,
Jamie Madilld4826152017-09-21 11:18:59 -0400246 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -0500247{
Frank Henigman739bd8b2017-06-19 21:02:27 -0400248 // Clip read area to framebuffer.
249 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
250 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
251 gl::Rectangle area;
252 if (!ClipRectangle(origArea, fbRect, &area))
253 {
254 // nothing to read
255 return gl::NoError();
256 }
257
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700258 const gl::PixelPackState &packState = context->getGLState().getPackState();
Jamie Madill87de3622015-03-16 10:41:44 -0400259
Geoff Langca271392017-04-05 12:30:00 -0400260 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
Corentin Wallez886de362016-09-27 10:49:35 -0400261
262 GLuint outputPitch = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400263 ANGLE_TRY_CHECKED_MATH(sizedFormatInfo.computeRowPitch(
264 type, origArea.width, packState.alignment, packState.rowLength, &outputPitch));
265
Olli Etuaho989cac32016-06-08 16:18:49 -0700266 GLuint outputSkipBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400267 ANGLE_TRY_CHECKED_MATH(
268 sizedFormatInfo.computeSkipBytes(type, outputPitch, 0, packState, false, &outputSkipBytes));
Frank Henigman739bd8b2017-06-19 21:02:27 -0400269 outputSkipBytes +=
270 (area.x - origArea.x) * sizedFormatInfo.pixelBytes + (area.y - origArea.y) * outputPitch;
Geoff Langbce529e2014-12-01 12:48:41 -0500271
Jamie Madill4928b7c2017-06-20 12:57:39 -0400272 return readPixelsImpl(context, area, format, type, outputPitch, packState,
Rafael Cintron05a449a2018-06-20 18:08:04 -0700273 static_cast<uint8_t *>(pixels) + outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500274}
275
Jamie Madillc564c072017-06-01 12:45:42 -0400276gl::Error FramebufferD3D::blit(const gl::Context *context,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400277 const gl::Rectangle &sourceArea,
278 const gl::Rectangle &destArea,
279 GLbitfield mask,
280 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500281{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700282 const auto &glState = context->getGLState();
Jamie Madill8415b5f2016-04-26 13:41:39 -0400283 const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
He Yunchao6be602d2016-12-22 14:33:07 +0800284 const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
Jamie Madillfe548342017-06-19 11:13:24 -0400285 ANGLE_TRY(blitImpl(context, sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0,
He Yunchao6be602d2016-12-22 14:33:07 +0800286 (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0,
287 filter, sourceFramebuffer));
Geoff Lang54bd5a42014-12-01 12:51:04 -0500288
He Yunchaoacd18982017-01-04 10:46:42 +0800289 return gl::NoError();
Geoff Lang54bd5a42014-12-01 12:51:04 -0500290}
291
Kenneth Russellce8602a2017-10-03 18:23:08 -0700292bool FramebufferD3D::checkStatus(const gl::Context *context) const
Geoff Lang748f74e2014-12-01 11:25:34 -0500293{
Geoff Langc2520562015-04-29 11:42:33 -0400294 // if we have both a depth and stencil buffer, they must refer to the same object
295 // since we only support packed_depth_stencil and not separate depth and stencil
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400296 if (mState.hasSeparateDepthAndStencilAttachments())
Geoff Langc2520562015-04-29 11:42:33 -0400297 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500298 return false;
Geoff Langc2520562015-04-29 11:42:33 -0400299 }
300
Kenneth Russellce8602a2017-10-03 18:23:08 -0700301 // D3D11 does not allow for overlapping RenderTargetViews.
302 // If WebGL compatibility is enabled, this has already been checked at a higher level.
303 ASSERT(!context->getExtensions().webglCompatibility || mState.colorAttachmentsAreUniqueImages());
304 if (!context->getExtensions().webglCompatibility)
Geoff Lang748f74e2014-12-01 11:25:34 -0500305 {
Kenneth Russellce8602a2017-10-03 18:23:08 -0700306 if (!mState.colorAttachmentsAreUniqueImages())
307 {
308 return false;
309 }
Geoff Lang748f74e2014-12-01 11:25:34 -0500310 }
311
Jamie Madillcc86d642015-11-24 13:00:07 -0500312 // D3D requires all render targets to have the same dimensions.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400313 if (!mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500314 {
315 return false;
316 }
317
318 return true;
Geoff Lang748f74e2014-12-01 11:25:34 -0500319}
320
Jamie Madill19fa1c62018-03-08 09:47:21 -0500321gl::Error FramebufferD3D::syncState(const gl::Context *context,
322 const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill7147f012015-03-05 15:41:40 -0500323{
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500324 if (!mColorAttachmentsForRender.valid())
Jamie Madill85a18042015-03-05 15:41:41 -0500325 {
Jamie Madill19fa1c62018-03-08 09:47:21 -0500326 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500327 }
328
Jamie Madill6de51852017-04-12 09:53:01 -0400329 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500330 {
331 if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
332 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
333 dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
334 {
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700335 mColorAttachmentsForRender.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500336 }
337 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500338
339 return gl::NoError();
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700340}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500341
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700342const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const gl::Context *context)
343{
344 gl::DrawBufferMask activeProgramOutputs =
345 context->getContextState().getState().getProgram()->getActiveOutputVariables();
346
347 if (mColorAttachmentsForRender.valid() && mCurrentActiveProgramOutputs == activeProgramOutputs)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500348 {
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700349 return mColorAttachmentsForRender.value();
Jamie Madill85a18042015-03-05 15:41:41 -0500350 }
351
Jamie Madill7147f012015-03-05 15:41:40 -0500352 // Does not actually free memory
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500353 gl::AttachmentList colorAttachmentsForRender;
Jamie Madill7147f012015-03-05 15:41:40 -0500354
Jamie Madill48ef11b2016-04-27 15:21:52 -0400355 const auto &colorAttachments = mState.getColorAttachments();
356 const auto &drawBufferStates = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500357 const auto &workarounds = mRenderer->getWorkarounds();
Jamie Madill2d06b732015-04-20 12:53:28 -0400358
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400359 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500360 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400361 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400362 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500363
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700364 if (colorAttachment.isAttached() && drawBufferState != GL_NONE &&
365 activeProgramOutputs[attachmentIndex])
Jamie Madill7147f012015-03-05 15:41:40 -0500366 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400367 ASSERT(drawBufferState == GL_BACK ||
368 drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500369 colorAttachmentsForRender.push_back(&colorAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -0500370 }
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400371 else if (!workarounds.mrtPerfWorkaround)
372 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500373 colorAttachmentsForRender.push_back(nullptr);
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400374 }
Jamie Madill7147f012015-03-05 15:41:40 -0500375 }
376
JiangYizhou38d92b52017-09-13 13:47:52 +0800377 // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel
378 // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel
379 // shader. We add a dummy texture as render target in such case.
380 if (mRenderer->getWorkarounds().addDummyTextureNoRenderTarget &&
Brandon Jones9fc87332017-12-13 15:46:52 -0800381 colorAttachmentsForRender.empty() && activeProgramOutputs.any())
JiangYizhou38d92b52017-09-13 13:47:52 +0800382 {
383 static_assert(static_cast<size_t>(activeProgramOutputs.size()) <= 32,
384 "Size of active program outputs should less or equal than 32.");
JiangYizhou10d41392017-12-18 18:13:36 +0800385 const GLuint activeProgramLocation = static_cast<GLuint>(
JiangYizhou38d92b52017-09-13 13:47:52 +0800386 gl::ScanForward(static_cast<uint32_t>(activeProgramOutputs.bits())));
387
JiangYizhou10d41392017-12-18 18:13:36 +0800388 if (mDummyAttachment.isAttached() &&
389 (mDummyAttachment.getBinding() - GL_COLOR_ATTACHMENT0) == activeProgramLocation)
JiangYizhou38d92b52017-09-13 13:47:52 +0800390 {
JiangYizhou10d41392017-12-18 18:13:36 +0800391 colorAttachmentsForRender.push_back(&mDummyAttachment);
392 }
393 else
394 {
395 // Remove dummy attachment to prevents us from leaking it, and the program may require
396 // it to be attached to a new binding point.
397 if (mDummyAttachment.isAttached())
398 {
399 mDummyAttachment.detach(context);
400 }
401
402 gl::Texture *dummyTex = nullptr;
403 // TODO(Jamie): Handle error if dummy texture can't be created.
Corentin Wallez99d492c2018-02-27 15:17:10 -0500404 ANGLE_SWALLOW_ERR(
405 mRenderer->getIncompleteTexture(context, gl::TextureType::_2D, &dummyTex));
JiangYizhou10d41392017-12-18 18:13:36 +0800406 if (dummyTex)
407 {
408
409 gl::ImageIndex index = gl::ImageIndex::Make2D(0);
410 mDummyAttachment = gl::FramebufferAttachment(
411 context, GL_TEXTURE, GL_COLOR_ATTACHMENT0_EXT + activeProgramLocation, index,
412 dummyTex);
413 colorAttachmentsForRender.push_back(&mDummyAttachment);
414 }
JiangYizhou38d92b52017-09-13 13:47:52 +0800415 }
416 }
417
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500418 mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700419 mCurrentActiveProgramOutputs = activeProgramOutputs;
Jamie Madill7147f012015-03-05 15:41:40 -0500420
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500421 return mColorAttachmentsForRender.value();
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500422}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500423
JiangYizhou10d41392017-12-18 18:13:36 +0800424void FramebufferD3D::destroy(const gl::Context *context)
425{
426 if (mDummyAttachment.isAttached())
427 {
428 mDummyAttachment.detach(context);
429 }
430}
431
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500432} // namespace rx