blob: f038a59de8a2c63476c15f89a6983335455ecba3 [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 Madill8415b5f2016-04-26 13:41:39 -0400100 ClearParameters clearParams = GetClearParameters(context->getState(), mask);
101 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 Madill8415b5f2016-04-26 13:41:39 -0400110 ClearParameters clearParams = GetClearParameters(context->getState(), 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 Madill8415b5f2016-04-26 13:41:39 -0400137 ClearParameters clearParams = GetClearParameters(context->getState(), 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 Madill8415b5f2016-04-26 13:41:39 -0400154 ClearParameters clearParams = GetClearParameters(context->getState(), 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 Madill8415b5f2016-04-26 13:41:39 -0400182 ClearParameters clearParams = GetClearParameters(context->getState(), 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 Madill8415b5f2016-04-26 13:41:39 -0400241 const gl::PixelPackState &packState = context->getState().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);
Minmin Gongadff67b2015-10-14 10:34:45 -0400245 GLuint outputPitch =
246 sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength);
247 GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels(
248 outputPitch, 0, 0, packState.skipRows, packState.skipPixels);
Geoff Langbce529e2014-12-01 12:48:41 -0500249
Minmin Gongadff67b2015-10-14 10:34:45 -0400250 return readPixelsImpl(area, format, type, outputPitch, packState,
251 reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500252}
253
Jamie Madill8415b5f2016-04-26 13:41:39 -0400254gl::Error FramebufferD3D::blit(ContextImpl *context,
255 const gl::Rectangle &sourceArea,
256 const gl::Rectangle &destArea,
257 GLbitfield mask,
258 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500259{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400260 const auto &glState = context->getState();
261 const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
Geoff Lang54bd5a42014-12-01 12:51:04 -0500262 bool blitRenderTarget = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400263 if ((mask & GL_COLOR_BUFFER_BIT) && sourceFramebuffer->getReadColorbuffer() != nullptr &&
264 mState.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500265 {
266 blitRenderTarget = true;
267 }
268
269 bool blitStencil = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400270 if ((mask & GL_STENCIL_BUFFER_BIT) && sourceFramebuffer->getStencilbuffer() != nullptr &&
271 mState.getStencilAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500272 {
273 blitStencil = true;
274 }
275
276 bool blitDepth = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400277 if ((mask & GL_DEPTH_BUFFER_BIT) && sourceFramebuffer->getDepthbuffer() != nullptr &&
278 mState.getDepthAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500279 {
280 blitDepth = true;
281 }
282
283 if (blitRenderTarget || blitDepth || blitStencil)
284 {
Jamie Madill8415b5f2016-04-26 13:41:39 -0400285 const gl::Rectangle *scissor =
286 glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
287 gl::Error error = blitImpl(sourceArea, destArea, scissor, blitRenderTarget, blitDepth,
288 blitStencil, filter, sourceFramebuffer);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500289 if (error.isError())
290 {
291 return error;
292 }
293 }
294
295 return gl::Error(GL_NO_ERROR);
296}
297
Jamie Madillcc86d642015-11-24 13:00:07 -0500298bool FramebufferD3D::checkStatus() const
Geoff Lang748f74e2014-12-01 11:25:34 -0500299{
Geoff Langc2520562015-04-29 11:42:33 -0400300 // if we have both a depth and stencil buffer, they must refer to the same object
301 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madill48ef11b2016-04-27 15:21:52 -0400302 if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr &&
303 mState.getDepthStencilAttachment() == nullptr)
Geoff Langc2520562015-04-29 11:42:33 -0400304 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500305 return false;
Geoff Langc2520562015-04-29 11:42:33 -0400306 }
307
Geoff Lang748f74e2014-12-01 11:25:34 -0500308 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madill48ef11b2016-04-27 15:21:52 -0400309 const auto &colorAttachments = mState.getColorAttachments();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400310 for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500311 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400312 const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment];
313 if (attachment.isAttached())
Geoff Lang748f74e2014-12-01 11:25:34 -0500314 {
315 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
316 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400317 const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment];
318 if (prevAttachment.isAttached() &&
319 (attachment.id() == prevAttachment.id() &&
320 attachment.type() == prevAttachment.type()))
Geoff Lang748f74e2014-12-01 11:25:34 -0500321 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500322 return false;
Geoff Lang748f74e2014-12-01 11:25:34 -0500323 }
324 }
325 }
326 }
327
Jamie Madillcc86d642015-11-24 13:00:07 -0500328 // D3D requires all render targets to have the same dimensions.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400329 if (!mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500330 {
331 return false;
332 }
333
334 return true;
Geoff Lang748f74e2014-12-01 11:25:34 -0500335}
336
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500337void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill7147f012015-03-05 15:41:40 -0500338{
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500339 bool invalidateColorAttachmentCache = false;
340
341 if (!mColorAttachmentsForRender.valid())
Jamie Madill85a18042015-03-05 15:41:41 -0500342 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500343 invalidateColorAttachmentCache = true;
344 }
345
346 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
347 {
348 if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
349 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
350 dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
351 {
352 invalidateColorAttachmentCache = true;
353 }
354 }
355
356 if (!invalidateColorAttachmentCache)
357 {
358 return;
Jamie Madill85a18042015-03-05 15:41:41 -0500359 }
360
Jamie Madill7147f012015-03-05 15:41:40 -0500361 // Does not actually free memory
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500362 gl::AttachmentList colorAttachmentsForRender;
Jamie Madill7147f012015-03-05 15:41:40 -0500363
Jamie Madill48ef11b2016-04-27 15:21:52 -0400364 const auto &colorAttachments = mState.getColorAttachments();
365 const auto &drawBufferStates = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500366 const auto &workarounds = mRenderer->getWorkarounds();
Jamie Madill2d06b732015-04-20 12:53:28 -0400367
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400368 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500369 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400370 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400371 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500372
Jamie Madill2d06b732015-04-20 12:53:28 -0400373 if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
Jamie Madill7147f012015-03-05 15:41:40 -0500374 {
375 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500376 colorAttachmentsForRender.push_back(&colorAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -0500377 }
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400378 else if (!workarounds.mrtPerfWorkaround)
379 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500380 colorAttachmentsForRender.push_back(nullptr);
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400381 }
Jamie Madill7147f012015-03-05 15:41:40 -0500382 }
383
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500384 mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
Jamie Madill7147f012015-03-05 15:41:40 -0500385}
386
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500387const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
388{
389 ASSERT(mColorAttachmentsForRender.valid());
390 return mColorAttachmentsForRender.value();
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500391}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500392
393} // namespace rx