blob: 334428110e6b1b43050b5d2270cc8ee04d7be45c [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
Jamie Madilld1405e52015-03-05 15:41:39 -050087FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
88 : FramebufferImpl(data),
89 mRenderer(renderer),
Jamie Madillb6bda4a2015-04-20 12:53:26 -040090 mColorAttachmentsForRender(mData.getColorAttachments().size(), nullptr),
Jamie Madill85a18042015-03-05 15:41:41 -050091 mInvalidateColorAttachmentCache(true)
Geoff Langda88add2014-12-01 10:22:01 -050092{
93 ASSERT(mRenderer != nullptr);
94}
95
96FramebufferD3D::~FramebufferD3D()
97{
98}
99
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400100void FramebufferD3D::onUpdateColorAttachment(size_t /*index*/)
Geoff Lang9dd95802014-12-01 11:12:59 -0500101{
Jamie Madill85a18042015-03-05 15:41:41 -0500102 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500103}
104
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400105void FramebufferD3D::onUpdateDepthAttachment()
Geoff Lang9dd95802014-12-01 11:12:59 -0500106{
107}
108
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400109void FramebufferD3D::onUpdateStencilAttachment()
Geoff Lang9dd95802014-12-01 11:12:59 -0500110{
111}
112
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400113void FramebufferD3D::onUpdateDepthStencilAttachment()
Geoff Lang9dd95802014-12-01 11:12:59 -0500114{
115}
116
Jamie Madill7147f012015-03-05 15:41:40 -0500117void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500118{
Jamie Madill85a18042015-03-05 15:41:41 -0500119 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500120}
121
Jamie Madill7147f012015-03-05 15:41:40 -0500122void FramebufferD3D::setReadBuffer(GLenum)
Geoff Lang9dd95802014-12-01 11:12:59 -0500123{
124}
125
Geoff Lang1ea584c2015-03-26 21:08:33 +0000126gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
127{
128 // No-op in D3D
129 return gl::Error(GL_NO_ERROR);
130}
131
132gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
133{
134 // No-op in D3D
135 return gl::Error(GL_NO_ERROR);
136}
137
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400138gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500139{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400140 const gl::State &state = *data.state;
Jamie Madillf75ab352015-03-16 10:46:52 -0400141 ClearParameters clearParams = GetClearParameters(state, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500142 return clear(state, clearParams);
143}
144
145gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
146{
147 // glClearBufferfv can be called to clear the color buffer or depth buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400148 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500149
150 if (buffer == GL_COLOR)
151 {
152 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
153 {
154 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
155 }
156 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
157 clearParams.colorClearType = GL_FLOAT;
158 }
159
160 if (buffer == GL_DEPTH)
161 {
162 clearParams.clearDepth = true;
163 clearParams.depthClearValue = values[0];
164 }
165
166 return clear(state, clearParams);
167}
168
169gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
170{
171 // glClearBufferuiv can only be called to clear a color buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400172 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500173 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
174 {
175 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
176 }
177 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
178 clearParams.colorClearType = GL_UNSIGNED_INT;
179
180 return clear(state, clearParams);
181}
182
183gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
184{
185 // glClearBufferiv can be called to clear the color buffer or stencil buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400186 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500187
188 if (buffer == GL_COLOR)
189 {
190 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
191 {
192 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
193 }
194 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
195 clearParams.colorClearType = GL_INT;
196 }
197
198 if (buffer == GL_STENCIL)
199 {
200 clearParams.clearStencil = true;
201 clearParams.stencilClearValue = values[1];
202 }
203
204 return clear(state, clearParams);
205}
206
207gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
208{
209 // glClearBufferfi can only be called to clear a depth stencil buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400210 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500211 clearParams.clearDepth = true;
212 clearParams.depthClearValue = depth;
213 clearParams.clearStencil = true;
214 clearParams.stencilClearValue = stencil;
215
216 return clear(state, clearParams);
217}
218
Geoff Langbce529e2014-12-01 12:48:41 -0500219GLenum FramebufferD3D::getImplementationColorReadFormat() const
220{
Jamie Madill7147f012015-03-05 15:41:40 -0500221 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500222
Jamie Madillb885e572015-02-03 16:16:04 -0500223 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500224 {
225 return GL_NONE;
226 }
227
Geoff Langc2e75af2015-01-05 14:26:24 -0500228 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madill8cf813c2015-05-04 12:55:18 -0400229 gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500230 if (error.isError())
231 {
232 return GL_NONE;
233 }
Geoff Langbce529e2014-12-01 12:48:41 -0500234
Geoff Langd8a22582014-12-17 15:28:23 -0500235 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
236 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
237
238 return implementationFormatInfo.format;
Geoff Langbce529e2014-12-01 12:48:41 -0500239}
240
241GLenum FramebufferD3D::getImplementationColorReadType() const
242{
Jamie Madill7147f012015-03-05 15:41:40 -0500243 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500244
Jamie Madillb885e572015-02-03 16:16:04 -0500245 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500246 {
247 return GL_NONE;
248 }
249
Geoff Langc2e75af2015-01-05 14:26:24 -0500250 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madill8cf813c2015-05-04 12:55:18 -0400251 gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500252 if (error.isError())
253 {
254 return GL_NONE;
255 }
Geoff Langbce529e2014-12-01 12:48:41 -0500256
Geoff Langd8a22582014-12-17 15:28:23 -0500257 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
258 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
259
260 return implementationFormatInfo.type;
Geoff Langbce529e2014-12-01 12:48:41 -0500261}
262
263gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
264{
Jamie Madill87de3622015-03-16 10:41:44 -0400265 const gl::PixelPackState &packState = state.getPackState();
266
267 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
268 {
269 UNIMPLEMENTED();
270 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
271 }
272
Geoff Langbce529e2014-12-01 12:48:41 -0500273 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
274 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Jamie Madill87de3622015-03-16 10:41:44 -0400275 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0);
Geoff Langbce529e2014-12-01 12:48:41 -0500276
Jamie Madill87de3622015-03-16 10:41:44 -0400277 return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels));
Geoff Langbce529e2014-12-01 12:48:41 -0500278}
279
Geoff Lang54bd5a42014-12-01 12:51:04 -0500280gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
281 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
282{
283 bool blitRenderTarget = false;
284 if ((mask & GL_COLOR_BUFFER_BIT) &&
285 sourceFramebuffer->getReadColorbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500286 mData.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500287 {
288 blitRenderTarget = true;
289 }
290
291 bool blitStencil = false;
292 if ((mask & GL_STENCIL_BUFFER_BIT) &&
293 sourceFramebuffer->getStencilbuffer() != nullptr &&
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400294 mData.getStencilAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500295 {
296 blitStencil = true;
297 }
298
299 bool blitDepth = false;
300 if ((mask & GL_DEPTH_BUFFER_BIT) &&
301 sourceFramebuffer->getDepthbuffer() != nullptr &&
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400302 mData.getDepthAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500303 {
304 blitDepth = true;
305 }
306
307 if (blitRenderTarget || blitDepth || blitStencil)
308 {
309 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
310 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
311 filter, sourceFramebuffer);
312 if (error.isError())
313 {
314 return error;
315 }
316 }
317
318 return gl::Error(GL_NO_ERROR);
319}
320
Geoff Lang748f74e2014-12-01 11:25:34 -0500321GLenum FramebufferD3D::checkStatus() const
322{
Geoff Langc2520562015-04-29 11:42:33 -0400323 // if we have both a depth and stencil buffer, they must refer to the same object
324 // since we only support packed_depth_stencil and not separate depth and stencil
325 if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr &&
326 mData.getDepthStencilAttachment() == nullptr)
327 {
328 return GL_FRAMEBUFFER_UNSUPPORTED;
329 }
330
Geoff Lang748f74e2014-12-01 11:25:34 -0500331 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400332 const auto &colorAttachments = mData.getColorAttachments();
333 for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500334 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400335 const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment];
336 if (attachment.isAttached())
Geoff Lang748f74e2014-12-01 11:25:34 -0500337 {
338 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
339 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400340 const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment];
341 if (prevAttachment.isAttached() &&
342 (attachment.id() == prevAttachment.id() &&
343 attachment.type() == prevAttachment.type()))
Geoff Lang748f74e2014-12-01 11:25:34 -0500344 {
345 return GL_FRAMEBUFFER_UNSUPPORTED;
346 }
347 }
348 }
349 }
350
351 return GL_FRAMEBUFFER_COMPLETE;
352}
353
Jamie Madill7147f012015-03-05 15:41:40 -0500354const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const
355{
Jamie Madill85a18042015-03-05 15:41:41 -0500356 if (!mInvalidateColorAttachmentCache)
357 {
358 return mColorAttachmentsForRender;
359 }
360
Jamie Madill7147f012015-03-05 15:41:40 -0500361 // Does not actually free memory
362 mColorAttachmentsForRender.clear();
363
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400364 const auto &colorAttachments = mData.getColorAttachments();
365 const auto &drawBufferStates = mData.getDrawBufferStates();
Jamie Madill2d06b732015-04-20 12:53:28 -0400366
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400367 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
Jamie Madill7147f012015-03-05 15:41:40 -0500368 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400369 GLenum drawBufferState = drawBufferStates[attachmentIndex];
Jamie Madill2d06b732015-04-20 12:53:28 -0400370 const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
Jamie Madill7147f012015-03-05 15:41:40 -0500371
Jamie Madill2d06b732015-04-20 12:53:28 -0400372 if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
Jamie Madill7147f012015-03-05 15:41:40 -0500373 {
374 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
Jamie Madill2d06b732015-04-20 12:53:28 -0400375 mColorAttachmentsForRender.push_back(&colorAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -0500376 }
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400377 else if (!workarounds.mrtPerfWorkaround)
378 {
379 mColorAttachmentsForRender.push_back(nullptr);
380 }
Jamie Madill7147f012015-03-05 15:41:40 -0500381 }
382
Jamie Madill85a18042015-03-05 15:41:41 -0500383 mInvalidateColorAttachmentCache = false;
Jamie Madill7147f012015-03-05 15:41:40 -0500384 return mColorAttachmentsForRender;
385}
386
Geoff Langb5d8f232014-12-04 15:43:01 -0500387// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
388unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
389{
390 if (attachment->type() == GL_TEXTURE)
391 {
392 gl::Texture *texture = attachment->getTexture();
393 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500394 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Jamie Madill8cf4a392015-04-02 11:36:04 -0400395 const gl::ImageIndex &index = attachment->getTextureImageIndex();
396 return textureD3D->getRenderTargetSerial(index);
Geoff Langb5d8f232014-12-04 15:43:01 -0500397 }
398 else if (attachment->type() == GL_RENDERBUFFER)
399 {
400 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
401 ASSERT(renderbuffer);
Jamie Madillf4bf3812015-04-01 16:15:32 -0400402 RenderbufferD3D *renderbufferD3D = GetImplAs<RenderbufferD3D>(renderbuffer);
Geoff Langb5d8f232014-12-04 15:43:01 -0500403 return renderbufferD3D->getRenderTargetSerial();
404 }
405 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
406 {
Jamie Madill5160ec12015-04-14 08:13:48 -0400407 const egl::Surface *surface = attachment->getSurface();
Jamie Madillc46f45d2015-03-31 13:20:55 -0400408 ASSERT(surface);
409 const SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
410 ASSERT(surfaceD3D);
411
Jamie Madill5160ec12015-04-14 08:13:48 -0400412 if (attachment->getBinding() == GL_BACK)
Jamie Madillc46f45d2015-03-31 13:20:55 -0400413 {
414 return surfaceD3D->getSwapChain()->getColorRenderTarget()->getSerial();
415 }
416 else
417 {
418 return surfaceD3D->getSwapChain()->getDepthStencilRenderTarget()->getSerial();
419 }
Geoff Langb5d8f232014-12-04 15:43:01 -0500420 }
421 else
422 {
423 UNREACHABLE();
424 return 0;
425 }
426}
427
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500428}