blob: 5be3c16faf6ccae1c91cd7c09eb1a2370a5f63e0 [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
Geoff Langbce529e2014-12-01 12:48:41 -050011#include "libANGLE/formatutils.h"
Geoff Lang54bd5a42014-12-01 12:51:04 -050012#include "libANGLE/Framebuffer.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050013#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040014#include "libANGLE/Surface.h"
15#include "libANGLE/renderer/d3d/RendererD3D.h"
16#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
17#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
18#include "libANGLE/renderer/d3d/SurfaceD3D.h"
19#include "libANGLE/renderer/d3d/SwapChainD3D.h"
20#include "libANGLE/renderer/d3d/TextureD3D.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050021
22namespace rx
23{
24
Jamie Madillf75ab352015-03-16 10:46:52 -040025namespace
26{
27
28ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
29{
30 ClearParameters clearParams;
31 memset(&clearParams, 0, sizeof(ClearParameters));
32
33 const auto &blendState = state.getBlendState();
34
35 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
36 {
37 clearParams.clearColor[i] = false;
38 }
39 clearParams.colorFClearValue = state.getColorClearValue();
40 clearParams.colorClearType = GL_FLOAT;
41 clearParams.colorMaskRed = blendState.colorMaskRed;
42 clearParams.colorMaskGreen = blendState.colorMaskGreen;
43 clearParams.colorMaskBlue = blendState.colorMaskBlue;
44 clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
45 clearParams.clearDepth = false;
46 clearParams.depthClearValue = state.getDepthClearValue();
47 clearParams.clearStencil = false;
48 clearParams.stencilClearValue = state.getStencilClearValue();
49 clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
50 clearParams.scissorEnabled = state.isScissorTestEnabled();
51 clearParams.scissor = state.getScissor();
52
53 const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
54 if (mask & GL_COLOR_BUFFER_BIT)
55 {
56 if (framebufferObject->hasEnabledColorAttachment())
57 {
58 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
59 {
60 clearParams.clearColor[i] = true;
61 }
62 }
63 }
64
65 if (mask & GL_DEPTH_BUFFER_BIT)
66 {
67 if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
68 {
69 clearParams.clearDepth = true;
70 }
71 }
72
73 if (mask & GL_STENCIL_BUFFER_BIT)
74 {
75 if (framebufferObject->getStencilbuffer() != NULL &&
76 framebufferObject->getStencilbuffer()->getStencilSize() > 0)
77 {
78 clearParams.clearStencil = true;
79 }
80 }
81
82 return clearParams;
83}
84
85}
86
Nico Weber44897142015-07-10 09:50:00 -070087FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data)
Jamie Madilld1405e52015-03-05 15:41:39 -050088 : FramebufferImpl(data),
Jamie Madillb6bda4a2015-04-20 12:53:26 -040089 mColorAttachmentsForRender(mData.getColorAttachments().size(), nullptr),
Nico Weber44897142015-07-10 09:50:00 -070090 mInvalidateColorAttachmentCache(true)
Geoff Langda88add2014-12-01 10:22:01 -050091{
Geoff Langda88add2014-12-01 10:22:01 -050092}
93
94FramebufferD3D::~FramebufferD3D()
95{
96}
97
Jamie Madill7d75e2b2015-04-30 09:42:18 -040098void FramebufferD3D::onUpdateColorAttachment(size_t /*index*/)
Geoff Lang9dd95802014-12-01 11:12:59 -050099{
Jamie Madill85a18042015-03-05 15:41:41 -0500100 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500101}
102
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400103void FramebufferD3D::onUpdateDepthAttachment()
Geoff Lang9dd95802014-12-01 11:12:59 -0500104{
105}
106
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400107void FramebufferD3D::onUpdateStencilAttachment()
Geoff Lang9dd95802014-12-01 11:12:59 -0500108{
109}
110
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400111void FramebufferD3D::onUpdateDepthStencilAttachment()
Geoff Lang9dd95802014-12-01 11:12:59 -0500112{
113}
114
Jamie Madill7147f012015-03-05 15:41:40 -0500115void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500116{
Jamie Madill85a18042015-03-05 15:41:41 -0500117 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500118}
119
Jamie Madill7147f012015-03-05 15:41:40 -0500120void FramebufferD3D::setReadBuffer(GLenum)
Geoff Lang9dd95802014-12-01 11:12:59 -0500121{
122}
123
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400124gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500125{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400126 const gl::State &state = *data.state;
Jamie Madillf75ab352015-03-16 10:46:52 -0400127 ClearParameters clearParams = GetClearParameters(state, mask);
Dian Xiang40281592015-11-19 18:24:44 -0800128 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500129}
130
Dian Xiang40281592015-11-19 18:24:44 -0800131gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data,
132 GLenum buffer,
133 GLint drawbuffer,
134 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500135{
136 // glClearBufferfv can be called to clear the color buffer or depth buffer
Dian Xiang40281592015-11-19 18:24:44 -0800137 ClearParameters clearParams = GetClearParameters(*data.state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500138
139 if (buffer == GL_COLOR)
140 {
141 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
142 {
143 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
144 }
145 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
146 clearParams.colorClearType = GL_FLOAT;
147 }
148
149 if (buffer == GL_DEPTH)
150 {
151 clearParams.clearDepth = true;
152 clearParams.depthClearValue = values[0];
153 }
154
Dian Xiang40281592015-11-19 18:24:44 -0800155 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500156}
157
Dian Xiang40281592015-11-19 18:24:44 -0800158gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data,
159 GLenum buffer,
160 GLint drawbuffer,
161 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500162{
163 // glClearBufferuiv can only be called to clear a color buffer
Dian Xiang40281592015-11-19 18:24:44 -0800164 ClearParameters clearParams = GetClearParameters(*data.state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500165 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
166 {
167 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
168 }
169 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
170 clearParams.colorClearType = GL_UNSIGNED_INT;
171
Dian Xiang40281592015-11-19 18:24:44 -0800172 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500173}
174
Dian Xiang40281592015-11-19 18:24:44 -0800175gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data,
176 GLenum buffer,
177 GLint drawbuffer,
178 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500179{
180 // glClearBufferiv can be called to clear the color buffer or stencil buffer
Dian Xiang40281592015-11-19 18:24:44 -0800181 ClearParameters clearParams = GetClearParameters(*data.state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500182
183 if (buffer == GL_COLOR)
184 {
185 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
186 {
187 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
188 }
189 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
190 clearParams.colorClearType = GL_INT;
191 }
192
193 if (buffer == GL_STENCIL)
194 {
195 clearParams.clearStencil = true;
196 clearParams.stencilClearValue = values[1];
197 }
198
Dian Xiang40281592015-11-19 18:24:44 -0800199 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500200}
201
Dian Xiang40281592015-11-19 18:24:44 -0800202gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data,
203 GLenum buffer,
204 GLint drawbuffer,
205 GLfloat depth,
206 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500207{
208 // glClearBufferfi can only be called to clear a depth stencil buffer
Dian Xiang40281592015-11-19 18:24:44 -0800209 ClearParameters clearParams = GetClearParameters(*data.state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500210 clearParams.clearDepth = true;
211 clearParams.depthClearValue = depth;
212 clearParams.clearStencil = true;
213 clearParams.stencilClearValue = stencil;
214
Dian Xiang40281592015-11-19 18:24:44 -0800215 return clear(data, clearParams);
Geoff Langb04dc822014-12-01 12:02:02 -0500216}
217
Geoff Langbce529e2014-12-01 12:48:41 -0500218GLenum FramebufferD3D::getImplementationColorReadFormat() const
219{
Jamie Madill7147f012015-03-05 15:41:40 -0500220 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500221
Jamie Madillb885e572015-02-03 16:16:04 -0500222 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500223 {
224 return GL_NONE;
225 }
226
Geoff Langc2e75af2015-01-05 14:26:24 -0500227 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madill8cf813c2015-05-04 12:55:18 -0400228 gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500229 if (error.isError())
230 {
231 return GL_NONE;
232 }
Geoff Langbce529e2014-12-01 12:48:41 -0500233
Geoff Langd8a22582014-12-17 15:28:23 -0500234 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
235 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
236
237 return implementationFormatInfo.format;
Geoff Langbce529e2014-12-01 12:48:41 -0500238}
239
240GLenum FramebufferD3D::getImplementationColorReadType() const
241{
Jamie Madill7147f012015-03-05 15:41:40 -0500242 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500243
Jamie Madillb885e572015-02-03 16:16:04 -0500244 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500245 {
246 return GL_NONE;
247 }
248
Geoff Langc2e75af2015-01-05 14:26:24 -0500249 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madill8cf813c2015-05-04 12:55:18 -0400250 gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500251 if (error.isError())
252 {
253 return GL_NONE;
254 }
Geoff Langbce529e2014-12-01 12:48:41 -0500255
Geoff Langd8a22582014-12-17 15:28:23 -0500256 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
257 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
258
259 return implementationFormatInfo.type;
Geoff Langbce529e2014-12-01 12:48:41 -0500260}
261
262gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
263{
Jamie Madill87de3622015-03-16 10:41:44 -0400264 const gl::PixelPackState &packState = state.getPackState();
265
Geoff Langbce529e2014-12-01 12:48:41 -0500266 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
267 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Minmin Gongadff67b2015-10-14 10:34:45 -0400268 GLuint outputPitch =
269 sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength);
270 GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels(
271 outputPitch, 0, 0, packState.skipRows, packState.skipPixels);
Geoff Langbce529e2014-12-01 12:48:41 -0500272
Minmin Gongadff67b2015-10-14 10:34:45 -0400273 return readPixelsImpl(area, format, type, outputPitch, packState,
274 reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
Geoff Langbce529e2014-12-01 12:48:41 -0500275}
276
Geoff Lang54bd5a42014-12-01 12:51:04 -0500277gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
278 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
279{
280 bool blitRenderTarget = false;
281 if ((mask & GL_COLOR_BUFFER_BIT) &&
282 sourceFramebuffer->getReadColorbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500283 mData.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500284 {
285 blitRenderTarget = true;
286 }
287
288 bool blitStencil = false;
289 if ((mask & GL_STENCIL_BUFFER_BIT) &&
290 sourceFramebuffer->getStencilbuffer() != nullptr &&
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400291 mData.getStencilAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500292 {
293 blitStencil = true;
294 }
295
296 bool blitDepth = false;
297 if ((mask & GL_DEPTH_BUFFER_BIT) &&
298 sourceFramebuffer->getDepthbuffer() != nullptr &&
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400299 mData.getDepthAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500300 {
301 blitDepth = true;
302 }
303
304 if (blitRenderTarget || blitDepth || blitStencil)
305 {
306 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
307 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
308 filter, sourceFramebuffer);
309 if (error.isError())
310 {
311 return error;
312 }
313 }
314
315 return gl::Error(GL_NO_ERROR);
316}
317
Jamie Madillcc86d642015-11-24 13:00:07 -0500318bool FramebufferD3D::checkStatus() const
Geoff Lang748f74e2014-12-01 11:25:34 -0500319{
Geoff Langc2520562015-04-29 11:42:33 -0400320 // if we have both a depth and stencil buffer, they must refer to the same object
321 // since we only support packed_depth_stencil and not separate depth and stencil
322 if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr &&
323 mData.getDepthStencilAttachment() == nullptr)
324 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500325 return false;
Geoff Langc2520562015-04-29 11:42:33 -0400326 }
327
Geoff Lang748f74e2014-12-01 11:25:34 -0500328 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400329 const auto &colorAttachments = mData.getColorAttachments();
330 for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500331 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400332 const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment];
333 if (attachment.isAttached())
Geoff Lang748f74e2014-12-01 11:25:34 -0500334 {
335 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
336 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400337 const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment];
338 if (prevAttachment.isAttached() &&
339 (attachment.id() == prevAttachment.id() &&
340 attachment.type() == prevAttachment.type()))
Geoff Lang748f74e2014-12-01 11:25:34 -0500341 {
Jamie Madillcc86d642015-11-24 13:00:07 -0500342 return false;
Geoff Lang748f74e2014-12-01 11:25:34 -0500343 }
344 }
345 }
346 }
347
Jamie Madillcc86d642015-11-24 13:00:07 -0500348 // D3D requires all render targets to have the same dimensions.
349 if (!mData.attachmentsHaveSameDimensions())
350 {
351 return false;
352 }
353
354 return true;
Geoff Lang748f74e2014-12-01 11:25:34 -0500355}
356
Geoff Lang6941a552015-07-27 11:06:45 -0400357const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(
358 const WorkaroundsD3D &workarounds) const
Jamie Madill7147f012015-03-05 15:41:40 -0500359{
Jamie Madill85a18042015-03-05 15:41:41 -0500360 if (!mInvalidateColorAttachmentCache)
361 {
362 return mColorAttachmentsForRender;
363 }
364
Jamie Madill7147f012015-03-05 15:41:40 -0500365 // Does not actually free memory
366 mColorAttachmentsForRender.clear();
367
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400368 const auto &colorAttachments = mData.getColorAttachments();
369 const auto &drawBufferStates = mData.getDrawBufferStates();
Jamie Madill2d06b732015-04-20 12:53:28 -0400370
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400371 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500372 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400373 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400374 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500375
Jamie Madill2d06b732015-04-20 12:53:28 -0400376 if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
Jamie Madill7147f012015-03-05 15:41:40 -0500377 {
378 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
Jamie Madill2d06b732015-04-20 12:53:28 -0400379 mColorAttachmentsForRender.push_back(&colorAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -0500380 }
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400381 else if (!workarounds.mrtPerfWorkaround)
382 {
383 mColorAttachmentsForRender.push_back(nullptr);
384 }
Jamie Madill7147f012015-03-05 15:41:40 -0500385 }
386
Jamie Madill85a18042015-03-05 15:41:41 -0500387 mInvalidateColorAttachmentCache = false;
Jamie Madill7147f012015-03-05 15:41:40 -0500388 return mColorAttachmentsForRender;
389}
390
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500391}