blob: 281a03730c7f8228aaf6e64f72107080c729404b [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"
16#include "libANGLE/renderer/d3d/RendererD3D.h"
17#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
18#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
19#include "libANGLE/renderer/d3d/SurfaceD3D.h"
20#include "libANGLE/renderer/d3d/SwapChainD3D.h"
21#include "libANGLE/renderer/d3d/TextureD3D.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050022
23namespace rx
24{
25
Jamie Madillf75ab352015-03-16 10:46:52 -040026namespace
27{
28
29ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
30{
31 ClearParameters clearParams;
32 memset(&clearParams, 0, sizeof(ClearParameters));
33
34 const auto &blendState = state.getBlendState();
35
36 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
37 {
38 clearParams.clearColor[i] = false;
39 }
40 clearParams.colorFClearValue = state.getColorClearValue();
41 clearParams.colorClearType = GL_FLOAT;
42 clearParams.colorMaskRed = blendState.colorMaskRed;
43 clearParams.colorMaskGreen = blendState.colorMaskGreen;
44 clearParams.colorMaskBlue = blendState.colorMaskBlue;
45 clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
46 clearParams.clearDepth = false;
47 clearParams.depthClearValue = state.getDepthClearValue();
48 clearParams.clearStencil = false;
49 clearParams.stencilClearValue = state.getStencilClearValue();
50 clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
51 clearParams.scissorEnabled = state.isScissorTestEnabled();
52 clearParams.scissor = state.getScissor();
53
54 const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
55 if (mask & GL_COLOR_BUFFER_BIT)
56 {
Geoff Langa15472a2015-08-11 11:48:03 -040057 if (framebufferObject->hasEnabledDrawBuffer())
Jamie Madillf75ab352015-03-16 10:46:52 -040058 {
59 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
60 {
61 clearParams.clearColor[i] = true;
62 }
63 }
64 }
65
66 if (mask & GL_DEPTH_BUFFER_BIT)
67 {
68 if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
69 {
70 clearParams.clearDepth = true;
71 }
72 }
73
74 if (mask & GL_STENCIL_BUFFER_BIT)
75 {
76 if (framebufferObject->getStencilbuffer() != NULL &&
77 framebufferObject->getStencilbuffer()->getStencilSize() > 0)
78 {
79 clearParams.clearStencil = true;
80 }
81 }
82
83 return clearParams;
84}
85
86}
87
Jamie Madill60ec6ea2016-01-22 15:27:19 -050088FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
89 : FramebufferImpl(data), mRenderer(renderer)
Geoff Langda88add2014-12-01 10:22:01 -050090{
Geoff Langda88add2014-12-01 10:22:01 -050091}
92
93FramebufferD3D::~FramebufferD3D()
94{
95}
96
Jamie Madill9082b982016-04-27 15:21:51 -040097gl::Error FramebufferD3D::clear(const gl::ContextState &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -050098{
Jamie Madilld1f5ef22015-04-01 14:17:06 -040099 const gl::State &state = *data.state;
Jamie Madillf75ab352015-03-16 10:46:52 -0400100 ClearParameters clearParams = GetClearParameters(state, mask);
Dian Xiang40281592015-11-19 18:24:44 -0800101 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500102}
103
Jamie Madill9082b982016-04-27 15:21:51 -0400104gl::Error FramebufferD3D::clearBufferfv(const gl::ContextState &data,
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
Dian Xiang40281592015-11-19 18:24:44 -0800110 ClearParameters clearParams = GetClearParameters(*data.state, 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
Dian Xiang40281592015-11-19 18:24:44 -0800128 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500129}
130
Jamie Madill9082b982016-04-27 15:21:51 -0400131gl::Error FramebufferD3D::clearBufferuiv(const gl::ContextState &data,
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
Dian Xiang40281592015-11-19 18:24:44 -0800137 ClearParameters clearParams = GetClearParameters(*data.state, 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
Dian Xiang40281592015-11-19 18:24:44 -0800145 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500146}
147
Jamie Madill9082b982016-04-27 15:21:51 -0400148gl::Error FramebufferD3D::clearBufferiv(const gl::ContextState &data,
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
Dian Xiang40281592015-11-19 18:24:44 -0800154 ClearParameters clearParams = GetClearParameters(*data.state, 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
Dian Xiang40281592015-11-19 18:24:44 -0800172 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500173}
174
Jamie Madill9082b982016-04-27 15:21:51 -0400175gl::Error FramebufferD3D::clearBufferfi(const gl::ContextState &data,
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
Dian Xiang40281592015-11-19 18:24:44 -0800182 ClearParameters clearParams = GetClearParameters(*data.state, 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
Dian Xiang40281592015-11-19 18:24:44 -0800188 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500189}
190
Geoff Langbce529e2014-12-01 12:48:41 -0500191GLenum FramebufferD3D::getImplementationColorReadFormat() const
192{
Jamie Madill7147f012015-03-05 15:41:40 -0500193 const gl::FramebufferAttachment *readAttachment = mData.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 Madill7147f012015-03-05 15:41:40 -0500215 const gl::FramebufferAttachment *readAttachment = mData.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
235gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
236{
Jamie Madill87de3622015-03-16 10:41:44 -0400237 const gl::PixelPackState &packState = state.getPackState();
238
Geoff Langbce529e2014-12-01 12:48:41 -0500239 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
240 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Minmin Gongadff67b2015-10-14 10:34:45 -0400241 GLuint outputPitch =
242 sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength);
243 GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels(
244 outputPitch, 0, 0, packState.skipRows, packState.skipPixels);
Geoff Langbce529e2014-12-01 12:48:41 -0500245
Minmin Gongadff67b2015-10-14 10:34:45 -0400246 return readPixelsImpl(area, format, type, outputPitch, packState,
247 reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500248}
249
Geoff Lang54bd5a42014-12-01 12:51:04 -0500250gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
251 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
252{
253 bool blitRenderTarget = false;
254 if ((mask & GL_COLOR_BUFFER_BIT) &&
255 sourceFramebuffer->getReadColorbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500256 mData.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500257 {
258 blitRenderTarget = true;
259 }
260
261 bool blitStencil = false;
262 if ((mask & GL_STENCIL_BUFFER_BIT) &&
263 sourceFramebuffer->getStencilbuffer() != nullptr &&
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400264 mData.getStencilAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500265 {
266 blitStencil = true;
267 }
268
269 bool blitDepth = false;
270 if ((mask & GL_DEPTH_BUFFER_BIT) &&
271 sourceFramebuffer->getDepthbuffer() != nullptr &&
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400272 mData.getDepthAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500273 {
274 blitDepth = true;
275 }
276
277 if (blitRenderTarget || blitDepth || blitStencil)
278 {
279 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
280 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
281 filter, sourceFramebuffer);
282 if (error.isError())
283 {
284 return error;
285 }
286 }
287
288 return gl::Error(GL_NO_ERROR);
289}
290
Jamie Madillcc86d642015-11-24 13:00:07 -0500291bool FramebufferD3D::checkStatus() const
Geoff Lang748f74e2014-12-01 11:25:34 -0500292{
Geoff Langc2520562015-04-29 11:42:33 -0400293 // if we have both a depth and stencil buffer, they must refer to the same object
294 // since we only support packed_depth_stencil and not separate depth and stencil
295 if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr &&
296 mData.getDepthStencilAttachment() == nullptr)
297 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500298 return false;
Geoff Langc2520562015-04-29 11:42:33 -0400299 }
300
Geoff Lang748f74e2014-12-01 11:25:34 -0500301 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400302 const auto &colorAttachments = mData.getColorAttachments();
303 for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500304 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400305 const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment];
306 if (attachment.isAttached())
Geoff Lang748f74e2014-12-01 11:25:34 -0500307 {
308 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
309 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400310 const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment];
311 if (prevAttachment.isAttached() &&
312 (attachment.id() == prevAttachment.id() &&
313 attachment.type() == prevAttachment.type()))
Geoff Lang748f74e2014-12-01 11:25:34 -0500314 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500315 return false;
Geoff Lang748f74e2014-12-01 11:25:34 -0500316 }
317 }
318 }
319 }
320
Jamie Madillcc86d642015-11-24 13:00:07 -0500321 // D3D requires all render targets to have the same dimensions.
322 if (!mData.attachmentsHaveSameDimensions())
323 {
324 return false;
325 }
326
327 return true;
Geoff Lang748f74e2014-12-01 11:25:34 -0500328}
329
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500330void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill7147f012015-03-05 15:41:40 -0500331{
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500332 bool invalidateColorAttachmentCache = false;
333
334 if (!mColorAttachmentsForRender.valid())
Jamie Madill85a18042015-03-05 15:41:41 -0500335 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500336 invalidateColorAttachmentCache = true;
337 }
338
339 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
340 {
341 if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
342 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
343 dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
344 {
345 invalidateColorAttachmentCache = true;
346 }
347 }
348
349 if (!invalidateColorAttachmentCache)
350 {
351 return;
Jamie Madill85a18042015-03-05 15:41:41 -0500352 }
353
Jamie Madill7147f012015-03-05 15:41:40 -0500354 // Does not actually free memory
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500355 gl::AttachmentList colorAttachmentsForRender;
Jamie Madill7147f012015-03-05 15:41:40 -0500356
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400357 const auto &colorAttachments = mData.getColorAttachments();
358 const auto &drawBufferStates = mData.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500359 const auto &workarounds = mRenderer->getWorkarounds();
Jamie Madill2d06b732015-04-20 12:53:28 -0400360
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400361 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500362 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400363 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400364 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500365
Jamie Madill2d06b732015-04-20 12:53:28 -0400366 if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
Jamie Madill7147f012015-03-05 15:41:40 -0500367 {
368 ASSERT(drawBufferState == GL_BACK || 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
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500377 mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
Jamie Madill7147f012015-03-05 15:41:40 -0500378}
379
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500380const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
381{
382 ASSERT(mColorAttachmentsForRender.valid());
383 return mColorAttachmentsForRender.value();
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500384}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500385
386} // namespace rx