blob: 32caca63fe4fb76773dd131425af7aaba32df1d7 [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 Madillabfbc0f2018-10-09 12:48:52 -040018#include "libANGLE/renderer/d3d/ContextD3D.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040019#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040020#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
21#include "libANGLE/renderer/d3d/RendererD3D.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040022#include "libANGLE/renderer/d3d/SurfaceD3D.h"
23#include "libANGLE/renderer/d3d/SwapChainD3D.h"
24#include "libANGLE/renderer/d3d/TextureD3D.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050025
26namespace rx
27{
28
Jamie Madillf75ab352015-03-16 10:46:52 -040029namespace
30{
31
32ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
33{
34 ClearParameters clearParams;
35 memset(&clearParams, 0, sizeof(ClearParameters));
36
37 const auto &blendState = state.getBlendState();
38
39 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
40 {
41 clearParams.clearColor[i] = false;
42 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -080043 clearParams.colorF = state.getColorClearValue();
44 clearParams.colorType = GL_FLOAT;
45 clearParams.colorMaskRed = blendState.colorMaskRed;
46 clearParams.colorMaskGreen = blendState.colorMaskGreen;
47 clearParams.colorMaskBlue = blendState.colorMaskBlue;
48 clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
49 clearParams.clearDepth = false;
50 clearParams.depthValue = state.getDepthClearValue();
51 clearParams.clearStencil = false;
52 clearParams.stencilValue = state.getStencilClearValue();
Jamie Madillf75ab352015-03-16 10:46:52 -040053 clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
Shahmeer Esmail5416f752017-03-09 22:02:43 -080054 clearParams.scissorEnabled = state.isScissorTestEnabled();
55 clearParams.scissor = state.getScissor();
Jamie Madillf75ab352015-03-16 10:46:52 -040056
57 const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
58 if (mask & GL_COLOR_BUFFER_BIT)
59 {
Geoff Langa15472a2015-08-11 11:48:03 -040060 if (framebufferObject->hasEnabledDrawBuffer())
Jamie Madillf75ab352015-03-16 10:46:52 -040061 {
62 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
63 {
64 clearParams.clearColor[i] = true;
65 }
66 }
67 }
68
69 if (mask & GL_DEPTH_BUFFER_BIT)
70 {
Yunchao He4f285442017-04-21 12:15:49 +080071 if (state.getDepthStencilState().depthMask &&
72 framebufferObject->getDepthbuffer() != nullptr)
Jamie Madillf75ab352015-03-16 10:46:52 -040073 {
74 clearParams.clearDepth = true;
75 }
76 }
77
78 if (mask & GL_STENCIL_BUFFER_BIT)
79 {
Yunchao He4f285442017-04-21 12:15:49 +080080 if (framebufferObject->getStencilbuffer() != nullptr &&
Jamie Madillf75ab352015-03-16 10:46:52 -040081 framebufferObject->getStencilbuffer()->getStencilSize() > 0)
82 {
83 clearParams.clearStencil = true;
84 }
85 }
86
87 return clearParams;
88}
Jamie Madillf75ab352015-03-16 10:46:52 -040089}
90
Jamie Madillacf2f3a2017-11-21 19:22:44 -050091ClearParameters::ClearParameters() = default;
92
93ClearParameters::ClearParameters(const ClearParameters &other) = default;
94
Jamie Madill48ef11b2016-04-27 15:21:52 -040095FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
JiangYizhou10d41392017-12-18 18:13:36 +080096 : FramebufferImpl(data), mRenderer(renderer), mDummyAttachment()
Geoff Langda88add2014-12-01 10:22:01 -050097{
Geoff Langda88add2014-12-01 10:22:01 -050098}
99
100FramebufferD3D::~FramebufferD3D()
101{
102}
103
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400104angle::Result FramebufferD3D::clear(const gl::Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500105{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700106 ClearParameters clearParams = GetClearParameters(context->getGLState(), mask);
Jamie Madill8415b5f2016-04-26 13:41:39 -0400107 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500108}
109
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400110angle::Result FramebufferD3D::clearBufferfv(const gl::Context *context,
111 GLenum buffer,
112 GLint drawbuffer,
113 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500114{
115 // glClearBufferfv can be called to clear the color buffer or depth buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700116 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500117
118 if (buffer == GL_COLOR)
119 {
120 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
121 {
122 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
123 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800124 clearParams.colorF = gl::ColorF(values[0], values[1], values[2], values[3]);
125 clearParams.colorType = GL_FLOAT;
Geoff Langb04dc822014-12-01 12:02:02 -0500126 }
127
128 if (buffer == GL_DEPTH)
129 {
130 clearParams.clearDepth = true;
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800131 clearParams.depthValue = values[0];
Geoff Langb04dc822014-12-01 12:02:02 -0500132 }
133
Jamie Madill8415b5f2016-04-26 13:41:39 -0400134 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500135}
136
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400137angle::Result FramebufferD3D::clearBufferuiv(const gl::Context *context,
138 GLenum buffer,
139 GLint drawbuffer,
140 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500141{
142 // glClearBufferuiv can only be called to clear a color buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700143 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500144 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
145 {
146 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
147 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800148 clearParams.colorUI = gl::ColorUI(values[0], values[1], values[2], values[3]);
149 clearParams.colorType = GL_UNSIGNED_INT;
Geoff Langb04dc822014-12-01 12:02:02 -0500150
Jamie Madill8415b5f2016-04-26 13:41:39 -0400151 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500152}
153
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400154angle::Result FramebufferD3D::clearBufferiv(const gl::Context *context,
155 GLenum buffer,
156 GLint drawbuffer,
157 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500158{
159 // glClearBufferiv can be called to clear the color buffer or stencil buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700160 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500161
162 if (buffer == GL_COLOR)
163 {
164 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
165 {
166 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
167 }
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800168 clearParams.colorI = gl::ColorI(values[0], values[1], values[2], values[3]);
169 clearParams.colorType = GL_INT;
Geoff Langb04dc822014-12-01 12:02:02 -0500170 }
171
172 if (buffer == GL_STENCIL)
173 {
174 clearParams.clearStencil = true;
Jamie Madill805d2812017-09-20 13:21:42 -0400175 clearParams.stencilValue = values[0];
Geoff Langb04dc822014-12-01 12:02:02 -0500176 }
177
Jamie Madill8415b5f2016-04-26 13:41:39 -0400178 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500179}
180
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400181angle::Result FramebufferD3D::clearBufferfi(const gl::Context *context,
182 GLenum buffer,
183 GLint drawbuffer,
184 GLfloat depth,
185 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500186{
187 // glClearBufferfi can only be called to clear a depth stencil buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700188 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Shahmeer Esmail5416f752017-03-09 22:02:43 -0800189 clearParams.clearDepth = true;
190 clearParams.depthValue = depth;
191 clearParams.clearStencil = true;
192 clearParams.stencilValue = stencil;
Geoff Langb04dc822014-12-01 12:02:02 -0500193
Jamie Madill8415b5f2016-04-26 13:41:39 -0400194 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500195}
196
Jamie Madill4928b7c2017-06-20 12:57:39 -0400197GLenum FramebufferD3D::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -0500198{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400199 const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500200
Jamie Madillb885e572015-02-03 16:16:04 -0500201 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500202 {
203 return GL_NONE;
204 }
205
Yunchao Hed7297bf2017-04-19 15:27:10 +0800206 RenderTargetD3D *attachmentRenderTarget = nullptr;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400207 gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500208 if (error.isError())
209 {
210 return GL_NONE;
211 }
Geoff Langbce529e2014-12-01 12:48:41 -0500212
Geoff Langd8a22582014-12-17 15:28:23 -0500213 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
Geoff Langca271392017-04-05 12:30:00 -0400214 const gl::InternalFormat &implementationFormatInfo =
215 gl::GetSizedInternalFormatInfo(implementationFormat);
Geoff Langd8a22582014-12-17 15:28:23 -0500216
Geoff Langf607c602016-09-21 11:46:48 -0400217 return implementationFormatInfo.getReadPixelsFormat();
Geoff Langbce529e2014-12-01 12:48:41 -0500218}
219
Jamie Madill4928b7c2017-06-20 12:57:39 -0400220GLenum FramebufferD3D::getImplementationColorReadType(const gl::Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -0500221{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400222 const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500223
Jamie Madillb885e572015-02-03 16:16:04 -0500224 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500225 {
226 return GL_NONE;
227 }
228
Yunchao Hed7297bf2017-04-19 15:27:10 +0800229 RenderTargetD3D *attachmentRenderTarget = nullptr;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400230 gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500231 if (error.isError())
232 {
233 return GL_NONE;
234 }
Geoff Langbce529e2014-12-01 12:48:41 -0500235
Geoff Langd8a22582014-12-17 15:28:23 -0500236 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
Geoff Langca271392017-04-05 12:30:00 -0400237 const gl::InternalFormat &implementationFormatInfo =
238 gl::GetSizedInternalFormatInfo(implementationFormat);
Geoff Langd8a22582014-12-17 15:28:23 -0500239
Geoff Langc71ea662017-09-26 17:06:02 -0400240 return implementationFormatInfo.getReadPixelsType(context->getClientVersion());
Geoff Langbce529e2014-12-01 12:48:41 -0500241}
242
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400243angle::Result FramebufferD3D::readPixels(const gl::Context *context,
244 const gl::Rectangle &area,
245 GLenum format,
246 GLenum type,
247 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -0500248{
Frank Henigman739bd8b2017-06-19 21:02:27 -0400249 // Clip read area to framebuffer.
250 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
251 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400252 gl::Rectangle clippedArea;
253 if (!ClipRectangle(area, fbRect, &clippedArea))
Frank Henigman739bd8b2017-06-19 21:02:27 -0400254 {
255 // nothing to read
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400256 return angle::Result::Continue();
Frank Henigman739bd8b2017-06-19 21:02:27 -0400257 }
258
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700259 const gl::PixelPackState &packState = context->getGLState().getPackState();
Jamie Madill87de3622015-03-16 10:41:44 -0400260
Geoff Langca271392017-04-05 12:30:00 -0400261 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
Corentin Wallez886de362016-09-27 10:49:35 -0400262
Jamie Madillabfbc0f2018-10-09 12:48:52 -0400263 ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
264
Corentin Wallez886de362016-09-27 10:49:35 -0400265 GLuint outputPitch = 0;
Jamie Madillabfbc0f2018-10-09 12:48:52 -0400266 ANGLE_CHECK_HR_MATH(contextD3D,
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400267 sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment,
Jamie Madillabfbc0f2018-10-09 12:48:52 -0400268 packState.rowLength, &outputPitch));
Jamie Madillca2ff382018-07-11 09:01:17 -0400269
Olli Etuaho989cac32016-06-08 16:18:49 -0700270 GLuint outputSkipBytes = 0;
Jamie Madillabfbc0f2018-10-09 12:48:52 -0400271 ANGLE_CHECK_HR_MATH(contextD3D, sizedFormatInfo.computeSkipBytes(
272 type, outputPitch, 0, packState, false, &outputSkipBytes));
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400273 outputSkipBytes += (clippedArea.x - area.x) * sizedFormatInfo.pixelBytes +
274 (clippedArea.y - area.y) * outputPitch;
Geoff Langbce529e2014-12-01 12:48:41 -0500275
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400276 return readPixelsImpl(context, clippedArea, format, type, outputPitch, packState,
Rafael Cintron05a449a2018-06-20 18:08:04 -0700277 static_cast<uint8_t *>(pixels) + outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500278}
279
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400280angle::Result FramebufferD3D::blit(const gl::Context *context,
281 const gl::Rectangle &sourceArea,
282 const gl::Rectangle &destArea,
283 GLbitfield mask,
284 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500285{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700286 const auto &glState = context->getGLState();
Jamie Madill8415b5f2016-04-26 13:41:39 -0400287 const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
He Yunchao6be602d2016-12-22 14:33:07 +0800288 const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
Jamie Madillfe548342017-06-19 11:13:24 -0400289 ANGLE_TRY(blitImpl(context, sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0,
He Yunchao6be602d2016-12-22 14:33:07 +0800290 (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0,
291 filter, sourceFramebuffer));
Geoff Lang54bd5a42014-12-01 12:51:04 -0500292
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400293 return angle::Result::Continue();
Geoff Lang54bd5a42014-12-01 12:51:04 -0500294}
295
Kenneth Russellce8602a2017-10-03 18:23:08 -0700296bool FramebufferD3D::checkStatus(const gl::Context *context) const
Geoff Lang748f74e2014-12-01 11:25:34 -0500297{
Geoff Langc2520562015-04-29 11:42:33 -0400298 // if we have both a depth and stencil buffer, they must refer to the same object
299 // since we only support packed_depth_stencil and not separate depth and stencil
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400300 if (mState.hasSeparateDepthAndStencilAttachments())
Geoff Langc2520562015-04-29 11:42:33 -0400301 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500302 return false;
Geoff Langc2520562015-04-29 11:42:33 -0400303 }
304
Kenneth Russellce8602a2017-10-03 18:23:08 -0700305 // D3D11 does not allow for overlapping RenderTargetViews.
306 // If WebGL compatibility is enabled, this has already been checked at a higher level.
307 ASSERT(!context->getExtensions().webglCompatibility || mState.colorAttachmentsAreUniqueImages());
308 if (!context->getExtensions().webglCompatibility)
Geoff Lang748f74e2014-12-01 11:25:34 -0500309 {
Kenneth Russellce8602a2017-10-03 18:23:08 -0700310 if (!mState.colorAttachmentsAreUniqueImages())
311 {
312 return false;
313 }
Geoff Lang748f74e2014-12-01 11:25:34 -0500314 }
315
Jamie Madillcc86d642015-11-24 13:00:07 -0500316 // D3D requires all render targets to have the same dimensions.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400317 if (!mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500318 {
319 return false;
320 }
321
322 return true;
Geoff Lang748f74e2014-12-01 11:25:34 -0500323}
324
Jamie Madill6f755b22018-10-09 12:48:54 -0400325angle::Result FramebufferD3D::syncState(const gl::Context *context,
326 const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill7147f012015-03-05 15:41:40 -0500327{
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500328 if (!mColorAttachmentsForRender.valid())
Jamie Madill85a18042015-03-05 15:41:41 -0500329 {
Jamie Madill6f755b22018-10-09 12:48:54 -0400330 return angle::Result::Continue();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500331 }
332
Jamie Madill6de51852017-04-12 09:53:01 -0400333 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500334 {
335 if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
336 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
337 dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
338 {
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700339 mColorAttachmentsForRender.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500340 }
341 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500342
Jamie Madill6f755b22018-10-09 12:48:54 -0400343 return angle::Result::Continue();
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700344}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500345
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700346const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const gl::Context *context)
347{
348 gl::DrawBufferMask activeProgramOutputs =
349 context->getContextState().getState().getProgram()->getActiveOutputVariables();
350
351 if (mColorAttachmentsForRender.valid() && mCurrentActiveProgramOutputs == activeProgramOutputs)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500352 {
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700353 return mColorAttachmentsForRender.value();
Jamie Madill85a18042015-03-05 15:41:41 -0500354 }
355
Jamie Madill7147f012015-03-05 15:41:40 -0500356 // Does not actually free memory
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500357 gl::AttachmentList colorAttachmentsForRender;
Jamie Madill7147f012015-03-05 15:41:40 -0500358
Jamie Madill48ef11b2016-04-27 15:21:52 -0400359 const auto &colorAttachments = mState.getColorAttachments();
360 const auto &drawBufferStates = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500361 const auto &workarounds = mRenderer->getWorkarounds();
Jamie Madill2d06b732015-04-20 12:53:28 -0400362
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400363 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500364 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400365 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400366 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500367
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700368 if (colorAttachment.isAttached() && drawBufferState != GL_NONE &&
369 activeProgramOutputs[attachmentIndex])
Jamie Madill7147f012015-03-05 15:41:40 -0500370 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400371 ASSERT(drawBufferState == GL_BACK ||
372 drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500373 colorAttachmentsForRender.push_back(&colorAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -0500374 }
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400375 else if (!workarounds.mrtPerfWorkaround)
376 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500377 colorAttachmentsForRender.push_back(nullptr);
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400378 }
Jamie Madill7147f012015-03-05 15:41:40 -0500379 }
380
JiangYizhou38d92b52017-09-13 13:47:52 +0800381 // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel
382 // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel
383 // shader. We add a dummy texture as render target in such case.
384 if (mRenderer->getWorkarounds().addDummyTextureNoRenderTarget &&
Brandon Jones9fc87332017-12-13 15:46:52 -0800385 colorAttachmentsForRender.empty() && activeProgramOutputs.any())
JiangYizhou38d92b52017-09-13 13:47:52 +0800386 {
387 static_assert(static_cast<size_t>(activeProgramOutputs.size()) <= 32,
388 "Size of active program outputs should less or equal than 32.");
JiangYizhou10d41392017-12-18 18:13:36 +0800389 const GLuint activeProgramLocation = static_cast<GLuint>(
JiangYizhou38d92b52017-09-13 13:47:52 +0800390 gl::ScanForward(static_cast<uint32_t>(activeProgramOutputs.bits())));
391
JiangYizhou10d41392017-12-18 18:13:36 +0800392 if (mDummyAttachment.isAttached() &&
393 (mDummyAttachment.getBinding() - GL_COLOR_ATTACHMENT0) == activeProgramLocation)
JiangYizhou38d92b52017-09-13 13:47:52 +0800394 {
JiangYizhou10d41392017-12-18 18:13:36 +0800395 colorAttachmentsForRender.push_back(&mDummyAttachment);
396 }
397 else
398 {
399 // Remove dummy attachment to prevents us from leaking it, and the program may require
400 // it to be attached to a new binding point.
401 if (mDummyAttachment.isAttached())
402 {
403 mDummyAttachment.detach(context);
404 }
405
406 gl::Texture *dummyTex = nullptr;
407 // TODO(Jamie): Handle error if dummy texture can't be created.
Jamie Madillec1fe5b2018-08-10 10:05:52 -0400408 (void)mRenderer->getIncompleteTexture(context, gl::TextureType::_2D, &dummyTex);
JiangYizhou10d41392017-12-18 18:13:36 +0800409 if (dummyTex)
410 {
411
412 gl::ImageIndex index = gl::ImageIndex::Make2D(0);
413 mDummyAttachment = gl::FramebufferAttachment(
414 context, GL_TEXTURE, GL_COLOR_ATTACHMENT0_EXT + activeProgramLocation, index,
415 dummyTex);
416 colorAttachmentsForRender.push_back(&mDummyAttachment);
417 }
JiangYizhou38d92b52017-09-13 13:47:52 +0800418 }
419 }
420
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500421 mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
Corentin Wallezdb9e5d32017-06-12 12:05:45 -0700422 mCurrentActiveProgramOutputs = activeProgramOutputs;
Jamie Madill7147f012015-03-05 15:41:40 -0500423
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500424 return mColorAttachmentsForRender.value();
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500425}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500426
JiangYizhou10d41392017-12-18 18:13:36 +0800427void FramebufferD3D::destroy(const gl::Context *context)
428{
429 if (mDummyAttachment.isAttached())
430 {
431 mDummyAttachment.detach(context);
432 }
433}
434
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500435} // namespace rx