blob: 19ad6f45a715714a7c347e37fc796ac70cc6087f [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);
Minmin Gongadff67b2015-10-14 10:34:45 -0400249 GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels(
Olli Etuaho95faa232016-06-07 14:01:53 -0700250 outputPitch, 0, 0, packState.skipRows, packState.skipPixels, false);
Geoff Langbce529e2014-12-01 12:48:41 -0500251
Minmin Gongadff67b2015-10-14 10:34:45 -0400252 return readPixelsImpl(area, format, type, outputPitch, packState,
253 reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500254}
255
Jamie Madill8415b5f2016-04-26 13:41:39 -0400256gl::Error FramebufferD3D::blit(ContextImpl *context,
257 const gl::Rectangle &sourceArea,
258 const gl::Rectangle &destArea,
259 GLbitfield mask,
260 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500261{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700262 const auto &glState = context->getGLState();
Jamie Madill8415b5f2016-04-26 13:41:39 -0400263 const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
Geoff Lang54bd5a42014-12-01 12:51:04 -0500264 bool blitRenderTarget = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400265 if ((mask & GL_COLOR_BUFFER_BIT) && sourceFramebuffer->getReadColorbuffer() != nullptr &&
266 mState.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500267 {
268 blitRenderTarget = true;
269 }
270
271 bool blitStencil = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400272 if ((mask & GL_STENCIL_BUFFER_BIT) && sourceFramebuffer->getStencilbuffer() != nullptr &&
273 mState.getStencilAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500274 {
275 blitStencil = true;
276 }
277
278 bool blitDepth = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400279 if ((mask & GL_DEPTH_BUFFER_BIT) && sourceFramebuffer->getDepthbuffer() != nullptr &&
280 mState.getDepthAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500281 {
282 blitDepth = true;
283 }
284
285 if (blitRenderTarget || blitDepth || blitStencil)
286 {
Jamie Madill8415b5f2016-04-26 13:41:39 -0400287 const gl::Rectangle *scissor =
288 glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
289 gl::Error error = blitImpl(sourceArea, destArea, scissor, blitRenderTarget, blitDepth,
290 blitStencil, filter, sourceFramebuffer);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500291 if (error.isError())
292 {
293 return error;
294 }
295 }
296
297 return gl::Error(GL_NO_ERROR);
298}
299
Jamie Madillcc86d642015-11-24 13:00:07 -0500300bool FramebufferD3D::checkStatus() const
Geoff Lang748f74e2014-12-01 11:25:34 -0500301{
Geoff Langc2520562015-04-29 11:42:33 -0400302 // if we have both a depth and stencil buffer, they must refer to the same object
303 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madill48ef11b2016-04-27 15:21:52 -0400304 if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr &&
305 mState.getDepthStencilAttachment() == nullptr)
Geoff Langc2520562015-04-29 11:42:33 -0400306 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500307 return false;
Geoff Langc2520562015-04-29 11:42:33 -0400308 }
309
Geoff Lang748f74e2014-12-01 11:25:34 -0500310 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madill48ef11b2016-04-27 15:21:52 -0400311 const auto &colorAttachments = mState.getColorAttachments();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400312 for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500313 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400314 const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment];
315 if (attachment.isAttached())
Geoff Lang748f74e2014-12-01 11:25:34 -0500316 {
317 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
318 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400319 const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment];
320 if (prevAttachment.isAttached() &&
321 (attachment.id() == prevAttachment.id() &&
322 attachment.type() == prevAttachment.type()))
Geoff Lang748f74e2014-12-01 11:25:34 -0500323 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500324 return false;
Geoff Lang748f74e2014-12-01 11:25:34 -0500325 }
326 }
327 }
328 }
329
Jamie Madillcc86d642015-11-24 13:00:07 -0500330 // D3D requires all render targets to have the same dimensions.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400331 if (!mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500332 {
333 return false;
334 }
335
336 return true;
Geoff Lang748f74e2014-12-01 11:25:34 -0500337}
338
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500339void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill7147f012015-03-05 15:41:40 -0500340{
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500341 bool invalidateColorAttachmentCache = false;
342
343 if (!mColorAttachmentsForRender.valid())
Jamie Madill85a18042015-03-05 15:41:41 -0500344 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500345 invalidateColorAttachmentCache = true;
346 }
347
348 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
349 {
350 if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
351 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
352 dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
353 {
354 invalidateColorAttachmentCache = true;
355 }
356 }
357
358 if (!invalidateColorAttachmentCache)
359 {
360 return;
Jamie Madill85a18042015-03-05 15:41:41 -0500361 }
362
Jamie Madill7147f012015-03-05 15:41:40 -0500363 // Does not actually free memory
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500364 gl::AttachmentList colorAttachmentsForRender;
Jamie Madill7147f012015-03-05 15:41:40 -0500365
Jamie Madill48ef11b2016-04-27 15:21:52 -0400366 const auto &colorAttachments = mState.getColorAttachments();
367 const auto &drawBufferStates = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500368 const auto &workarounds = mRenderer->getWorkarounds();
Jamie Madill2d06b732015-04-20 12:53:28 -0400369
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400370 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500371 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400372 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400373 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500374
Jamie Madill2d06b732015-04-20 12:53:28 -0400375 if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
Jamie Madill7147f012015-03-05 15:41:40 -0500376 {
377 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500378 colorAttachmentsForRender.push_back(&colorAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -0500379 }
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400380 else if (!workarounds.mrtPerfWorkaround)
381 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500382 colorAttachmentsForRender.push_back(nullptr);
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400383 }
Jamie Madill7147f012015-03-05 15:41:40 -0500384 }
385
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500386 mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
Jamie Madill7147f012015-03-05 15:41:40 -0500387}
388
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500389const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
390{
391 ASSERT(mColorAttachmentsForRender.valid());
392 return mColorAttachmentsForRender.value();
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500393}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500394
395} // namespace rx