blob: a45c94538cfdb968d1ac2cb4a09ceb1e33703b56 [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 Madill60ec6ea2016-01-22 15:27:19 -050011#include "common/BitSetIterator.h"
Geoff Langbce529e2014-12-01 12:48:41 -050012#include "libANGLE/formatutils.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 Madill8415b5f2016-04-26 13:41:39 -040016#include "libANGLE/renderer/ContextImpl.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040017#include "libANGLE/renderer/d3d/RendererD3D.h"
18#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
19#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
20#include "libANGLE/renderer/d3d/SurfaceD3D.h"
21#include "libANGLE/renderer/d3d/SwapChainD3D.h"
22#include "libANGLE/renderer/d3d/TextureD3D.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050023
24namespace rx
25{
26
Jamie Madillf75ab352015-03-16 10:46:52 -040027namespace
28{
29
30ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
31{
32 ClearParameters clearParams;
33 memset(&clearParams, 0, sizeof(ClearParameters));
34
35 const auto &blendState = state.getBlendState();
36
37 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
38 {
39 clearParams.clearColor[i] = false;
40 }
41 clearParams.colorFClearValue = state.getColorClearValue();
42 clearParams.colorClearType = GL_FLOAT;
43 clearParams.colorMaskRed = blendState.colorMaskRed;
44 clearParams.colorMaskGreen = blendState.colorMaskGreen;
45 clearParams.colorMaskBlue = blendState.colorMaskBlue;
46 clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
47 clearParams.clearDepth = false;
48 clearParams.depthClearValue = state.getDepthClearValue();
49 clearParams.clearStencil = false;
50 clearParams.stencilClearValue = state.getStencilClearValue();
51 clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
52 clearParams.scissorEnabled = state.isScissorTestEnabled();
53 clearParams.scissor = state.getScissor();
54
55 const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
56 if (mask & GL_COLOR_BUFFER_BIT)
57 {
Geoff Langa15472a2015-08-11 11:48:03 -040058 if (framebufferObject->hasEnabledDrawBuffer())
Jamie Madillf75ab352015-03-16 10:46:52 -040059 {
60 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
61 {
62 clearParams.clearColor[i] = true;
63 }
64 }
65 }
66
67 if (mask & GL_DEPTH_BUFFER_BIT)
68 {
69 if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
70 {
71 clearParams.clearDepth = true;
72 }
73 }
74
75 if (mask & GL_STENCIL_BUFFER_BIT)
76 {
77 if (framebufferObject->getStencilbuffer() != NULL &&
78 framebufferObject->getStencilbuffer()->getStencilSize() > 0)
79 {
80 clearParams.clearStencil = true;
81 }
82 }
83
84 return clearParams;
85}
86
87}
88
Jamie Madill48ef11b2016-04-27 15:21:52 -040089FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
Jamie Madill60ec6ea2016-01-22 15:27:19 -050090 : FramebufferImpl(data), mRenderer(renderer)
Geoff Langda88add2014-12-01 10:22:01 -050091{
Geoff Langda88add2014-12-01 10:22:01 -050092}
93
94FramebufferD3D::~FramebufferD3D()
95{
96}
97
Jamie Madill8415b5f2016-04-26 13:41:39 -040098gl::Error FramebufferD3D::clear(ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -050099{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700100 ClearParameters clearParams = GetClearParameters(context->getGLState(), mask);
Jamie Madill8415b5f2016-04-26 13:41:39 -0400101 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500102}
103
Jamie Madill8415b5f2016-04-26 13:41:39 -0400104gl::Error FramebufferD3D::clearBufferfv(ContextImpl *context,
Dian Xiang40281592015-11-19 18:24:44 -0800105 GLenum buffer,
106 GLint drawbuffer,
107 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500108{
109 // glClearBufferfv can be called to clear the color buffer or depth buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700110 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500111
112 if (buffer == GL_COLOR)
113 {
114 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
115 {
116 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
117 }
118 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
119 clearParams.colorClearType = GL_FLOAT;
120 }
121
122 if (buffer == GL_DEPTH)
123 {
124 clearParams.clearDepth = true;
125 clearParams.depthClearValue = values[0];
126 }
127
Jamie Madill8415b5f2016-04-26 13:41:39 -0400128 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500129}
130
Jamie Madill8415b5f2016-04-26 13:41:39 -0400131gl::Error FramebufferD3D::clearBufferuiv(ContextImpl *context,
Dian Xiang40281592015-11-19 18:24:44 -0800132 GLenum buffer,
133 GLint drawbuffer,
134 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500135{
136 // glClearBufferuiv can only be called to clear a color buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700137 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500138 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
139 {
140 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
141 }
142 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
143 clearParams.colorClearType = GL_UNSIGNED_INT;
144
Jamie Madill8415b5f2016-04-26 13:41:39 -0400145 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500146}
147
Jamie Madill8415b5f2016-04-26 13:41:39 -0400148gl::Error FramebufferD3D::clearBufferiv(ContextImpl *context,
Dian Xiang40281592015-11-19 18:24:44 -0800149 GLenum buffer,
150 GLint drawbuffer,
151 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500152{
153 // glClearBufferiv can be called to clear the color buffer or stencil buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700154 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500155
156 if (buffer == GL_COLOR)
157 {
158 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
159 {
160 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
161 }
162 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
163 clearParams.colorClearType = GL_INT;
164 }
165
166 if (buffer == GL_STENCIL)
167 {
168 clearParams.clearStencil = true;
169 clearParams.stencilClearValue = values[1];
170 }
171
Jamie Madill8415b5f2016-04-26 13:41:39 -0400172 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500173}
174
Jamie Madill8415b5f2016-04-26 13:41:39 -0400175gl::Error FramebufferD3D::clearBufferfi(ContextImpl *context,
Dian Xiang40281592015-11-19 18:24:44 -0800176 GLenum buffer,
177 GLint drawbuffer,
178 GLfloat depth,
179 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500180{
181 // glClearBufferfi can only be called to clear a depth stencil buffer
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700182 ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500183 clearParams.clearDepth = true;
184 clearParams.depthClearValue = depth;
185 clearParams.clearStencil = true;
186 clearParams.stencilClearValue = stencil;
187
Jamie Madill8415b5f2016-04-26 13:41:39 -0400188 return clearImpl(context, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500189}
190
Geoff Langbce529e2014-12-01 12:48:41 -0500191GLenum FramebufferD3D::getImplementationColorReadFormat() const
192{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400193 const gl::FramebufferAttachment *readAttachment = mState.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 Madill8cf813c2015-05-04 12:55:18 -0400201 gl::Error error = readAttachment->getRenderTarget(&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 Madill48ef11b2016-04-27 15:21:52 -0400215 const gl::FramebufferAttachment *readAttachment = mState.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 Madill8cf813c2015-05-04 12:55:18 -0400223 gl::Error error = readAttachment->getRenderTarget(&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
Jamie Madill8415b5f2016-04-26 13:41:39 -0400235gl::Error FramebufferD3D::readPixels(ContextImpl *context,
236 const gl::Rectangle &area,
237 GLenum format,
238 GLenum type,
239 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500240{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700241 const gl::PixelPackState &packState = context->getGLState().getPackState();
Jamie Madill87de3622015-03-16 10:41:44 -0400242
Geoff Langbce529e2014-12-01 12:48:41 -0500243 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
244 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Jamie Madille2e406c2016-06-02 13:04:10 -0400245 GLuint outputPitch = 0;
246 ANGLE_TRY_RESULT(
247 sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength),
248 outputPitch);
Olli Etuaho989cac32016-06-08 16:18:49 -0700249 GLuint outputSkipBytes = 0;
250 ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, 0, packState.skipRows,
251 packState.skipPixels, false),
252 outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500253
Minmin Gongadff67b2015-10-14 10:34:45 -0400254 return readPixelsImpl(area, format, type, outputPitch, packState,
255 reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500256}
257
Jamie Madill8415b5f2016-04-26 13:41:39 -0400258gl::Error FramebufferD3D::blit(ContextImpl *context,
259 const gl::Rectangle &sourceArea,
260 const gl::Rectangle &destArea,
261 GLbitfield mask,
262 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500263{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700264 const auto &glState = context->getGLState();
Jamie Madill8415b5f2016-04-26 13:41:39 -0400265 const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
Geoff Lang54bd5a42014-12-01 12:51:04 -0500266 bool blitRenderTarget = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400267 if ((mask & GL_COLOR_BUFFER_BIT) && sourceFramebuffer->getReadColorbuffer() != nullptr &&
268 mState.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500269 {
270 blitRenderTarget = true;
271 }
272
273 bool blitStencil = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400274 if ((mask & GL_STENCIL_BUFFER_BIT) && sourceFramebuffer->getStencilbuffer() != nullptr &&
275 mState.getStencilAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500276 {
277 blitStencil = true;
278 }
279
280 bool blitDepth = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400281 if ((mask & GL_DEPTH_BUFFER_BIT) && sourceFramebuffer->getDepthbuffer() != nullptr &&
282 mState.getDepthAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500283 {
284 blitDepth = true;
285 }
286
287 if (blitRenderTarget || blitDepth || blitStencil)
288 {
Jamie Madill8415b5f2016-04-26 13:41:39 -0400289 const gl::Rectangle *scissor =
290 glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
291 gl::Error error = blitImpl(sourceArea, destArea, scissor, blitRenderTarget, blitDepth,
292 blitStencil, filter, sourceFramebuffer);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500293 if (error.isError())
294 {
295 return error;
296 }
297 }
298
299 return gl::Error(GL_NO_ERROR);
300}
301
Jamie Madillcc86d642015-11-24 13:00:07 -0500302bool FramebufferD3D::checkStatus() const
Geoff Lang748f74e2014-12-01 11:25:34 -0500303{
Geoff Langc2520562015-04-29 11:42:33 -0400304 // if we have both a depth and stencil buffer, they must refer to the same object
305 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madill48ef11b2016-04-27 15:21:52 -0400306 if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr &&
307 mState.getDepthStencilAttachment() == nullptr)
Geoff Langc2520562015-04-29 11:42:33 -0400308 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500309 return false;
Geoff Langc2520562015-04-29 11:42:33 -0400310 }
311
Geoff Langb21e20d2016-07-19 15:35:41 -0400312 // D3D11 does not allow for overlapping RenderTargetViews
313 if (!mState.colorAttachmentsAreUniqueImages())
Geoff Lang748f74e2014-12-01 11:25:34 -0500314 {
Geoff Langb21e20d2016-07-19 15:35:41 -0400315 return false;
Geoff Lang748f74e2014-12-01 11:25:34 -0500316 }
317
Jamie Madillcc86d642015-11-24 13:00:07 -0500318 // D3D requires all render targets to have the same dimensions.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400319 if (!mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500320 {
321 return false;
322 }
323
324 return true;
Geoff Lang748f74e2014-12-01 11:25:34 -0500325}
326
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500327void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill7147f012015-03-05 15:41:40 -0500328{
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500329 bool invalidateColorAttachmentCache = false;
330
331 if (!mColorAttachmentsForRender.valid())
Jamie Madill85a18042015-03-05 15:41:41 -0500332 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500333 invalidateColorAttachmentCache = true;
334 }
335
336 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
337 {
338 if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
339 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
340 dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
341 {
342 invalidateColorAttachmentCache = true;
343 }
344 }
345
346 if (!invalidateColorAttachmentCache)
347 {
348 return;
Jamie Madill85a18042015-03-05 15:41:41 -0500349 }
350
Jamie Madill7147f012015-03-05 15:41:40 -0500351 // Does not actually free memory
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500352 gl::AttachmentList colorAttachmentsForRender;
Jamie Madill7147f012015-03-05 15:41:40 -0500353
Jamie Madill48ef11b2016-04-27 15:21:52 -0400354 const auto &colorAttachments = mState.getColorAttachments();
355 const auto &drawBufferStates = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500356 const auto &workarounds = mRenderer->getWorkarounds();
Jamie Madill2d06b732015-04-20 12:53:28 -0400357
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400358 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500359 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400360 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400361 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500362
Jamie Madill2d06b732015-04-20 12:53:28 -0400363 if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
Jamie Madill7147f012015-03-05 15:41:40 -0500364 {
365 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500366 colorAttachmentsForRender.push_back(&colorAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -0500367 }
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400368 else if (!workarounds.mrtPerfWorkaround)
369 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500370 colorAttachmentsForRender.push_back(nullptr);
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400371 }
Jamie Madill7147f012015-03-05 15:41:40 -0500372 }
373
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500374 mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
Jamie Madill7147f012015-03-05 15:41:40 -0500375}
376
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500377const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
378{
379 ASSERT(mColorAttachmentsForRender.valid());
380 return mColorAttachmentsForRender.value();
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500381}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500382
383} // namespace rx