blob: 7ef36eaa59830312c4b4d6f7503dd4ab76333509 [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"
Geoff Langb5d8f232014-12-04 15:43:01 -050010#include "libANGLE/renderer/d3d/TextureD3D.h"
Geoff Langda88add2014-12-01 10:22:01 -050011#include "libANGLE/renderer/d3d/RendererD3D.h"
Geoff Langc2e75af2015-01-05 14:26:24 -050012#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050013#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
Geoff Langbce529e2014-12-01 12:48:41 -050014#include "libANGLE/formatutils.h"
Geoff Lang54bd5a42014-12-01 12:51:04 -050015#include "libANGLE/Framebuffer.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050016#include "libANGLE/FramebufferAttachment.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050017
18namespace rx
19{
20
Jamie Madillf75ab352015-03-16 10:46:52 -040021namespace
22{
23
24ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
25{
26 ClearParameters clearParams;
27 memset(&clearParams, 0, sizeof(ClearParameters));
28
29 const auto &blendState = state.getBlendState();
30
31 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
32 {
33 clearParams.clearColor[i] = false;
34 }
35 clearParams.colorFClearValue = state.getColorClearValue();
36 clearParams.colorClearType = GL_FLOAT;
37 clearParams.colorMaskRed = blendState.colorMaskRed;
38 clearParams.colorMaskGreen = blendState.colorMaskGreen;
39 clearParams.colorMaskBlue = blendState.colorMaskBlue;
40 clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
41 clearParams.clearDepth = false;
42 clearParams.depthClearValue = state.getDepthClearValue();
43 clearParams.clearStencil = false;
44 clearParams.stencilClearValue = state.getStencilClearValue();
45 clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
46 clearParams.scissorEnabled = state.isScissorTestEnabled();
47 clearParams.scissor = state.getScissor();
48
49 const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
50 if (mask & GL_COLOR_BUFFER_BIT)
51 {
52 if (framebufferObject->hasEnabledColorAttachment())
53 {
54 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
55 {
56 clearParams.clearColor[i] = true;
57 }
58 }
59 }
60
61 if (mask & GL_DEPTH_BUFFER_BIT)
62 {
63 if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
64 {
65 clearParams.clearDepth = true;
66 }
67 }
68
69 if (mask & GL_STENCIL_BUFFER_BIT)
70 {
71 if (framebufferObject->getStencilbuffer() != NULL &&
72 framebufferObject->getStencilbuffer()->getStencilSize() > 0)
73 {
74 clearParams.clearStencil = true;
75 }
76 }
77
78 return clearParams;
79}
80
81}
82
Geoff Langc2e75af2015-01-05 14:26:24 -050083DefaultAttachmentD3D::DefaultAttachmentD3D(RenderTargetD3D *renderTarget)
Geoff Lang6a1e6b92014-11-06 10:42:45 -050084 : mRenderTarget(renderTarget)
85{
86 ASSERT(mRenderTarget);
87}
88
89DefaultAttachmentD3D::~DefaultAttachmentD3D()
90{
91 SafeDelete(mRenderTarget);
92}
93
94DefaultAttachmentD3D *DefaultAttachmentD3D::makeDefaultAttachmentD3D(DefaultAttachmentImpl* impl)
95{
96 ASSERT(HAS_DYNAMIC_TYPE(DefaultAttachmentD3D*, impl));
97 return static_cast<DefaultAttachmentD3D*>(impl);
98}
99
100GLsizei DefaultAttachmentD3D::getWidth() const
101{
102 return mRenderTarget->getWidth();
103}
104
105GLsizei DefaultAttachmentD3D::getHeight() const
106{
107 return mRenderTarget->getHeight();
108}
109
110GLenum DefaultAttachmentD3D::getInternalFormat() const
111{
112 return mRenderTarget->getInternalFormat();
113}
114
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500115GLsizei DefaultAttachmentD3D::getSamples() const
116{
117 return mRenderTarget->getSamples();
118}
119
Geoff Langc2e75af2015-01-05 14:26:24 -0500120RenderTargetD3D *DefaultAttachmentD3D::getRenderTarget() const
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500121{
122 return mRenderTarget;
123}
124
Jamie Madilld1405e52015-03-05 15:41:39 -0500125FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
126 : FramebufferImpl(data),
127 mRenderer(renderer),
Jamie Madill85a18042015-03-05 15:41:41 -0500128 mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr),
129 mInvalidateColorAttachmentCache(true)
Geoff Langda88add2014-12-01 10:22:01 -0500130{
131 ASSERT(mRenderer != nullptr);
132}
133
134FramebufferD3D::~FramebufferD3D()
135{
136}
137
Jamie Madill7147f012015-03-05 15:41:40 -0500138void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500139{
Jamie Madill85a18042015-03-05 15:41:41 -0500140 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500141}
142
Jamie Madillf90353e2015-03-05 19:37:58 -0500143void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500144{
145}
146
Jamie Madill7147f012015-03-05 15:41:40 -0500147void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500148{
149}
150
Jamie Madill7147f012015-03-05 15:41:40 -0500151void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500152{
153}
154
Jamie Madill7147f012015-03-05 15:41:40 -0500155void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
Geoff Lang9dd95802014-12-01 11:12:59 -0500156{
Jamie Madill85a18042015-03-05 15:41:41 -0500157 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -0500158}
159
Jamie Madill7147f012015-03-05 15:41:40 -0500160void FramebufferD3D::setReadBuffer(GLenum)
Geoff Lang9dd95802014-12-01 11:12:59 -0500161{
162}
163
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500164gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
165{
166 // No-op in D3D
167 return gl::Error(GL_NO_ERROR);
168}
169
170gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
171{
172 // No-op in D3D
173 return gl::Error(GL_NO_ERROR);
174}
175
Geoff Langb04dc822014-12-01 12:02:02 -0500176gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
177{
Jamie Madillf75ab352015-03-16 10:46:52 -0400178 ClearParameters clearParams = GetClearParameters(state, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500179 return clear(state, clearParams);
180}
181
182gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
183{
184 // glClearBufferfv can be called to clear the color buffer or depth buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400185 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500186
187 if (buffer == GL_COLOR)
188 {
189 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
190 {
191 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
192 }
193 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
194 clearParams.colorClearType = GL_FLOAT;
195 }
196
197 if (buffer == GL_DEPTH)
198 {
199 clearParams.clearDepth = true;
200 clearParams.depthClearValue = values[0];
201 }
202
203 return clear(state, clearParams);
204}
205
206gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
207{
208 // glClearBufferuiv can only be called to clear a color buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400209 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500210 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
211 {
212 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
213 }
214 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
215 clearParams.colorClearType = GL_UNSIGNED_INT;
216
217 return clear(state, clearParams);
218}
219
220gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
221{
222 // glClearBufferiv can be called to clear the color buffer or stencil buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400223 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500224
225 if (buffer == GL_COLOR)
226 {
227 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
228 {
229 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
230 }
231 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
232 clearParams.colorClearType = GL_INT;
233 }
234
235 if (buffer == GL_STENCIL)
236 {
237 clearParams.clearStencil = true;
238 clearParams.stencilClearValue = values[1];
239 }
240
241 return clear(state, clearParams);
242}
243
244gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
245{
246 // glClearBufferfi can only be called to clear a depth stencil buffer
Jamie Madillf75ab352015-03-16 10:46:52 -0400247 ClearParameters clearParams = GetClearParameters(state, 0);
Geoff Langb04dc822014-12-01 12:02:02 -0500248 clearParams.clearDepth = true;
249 clearParams.depthClearValue = depth;
250 clearParams.clearStencil = true;
251 clearParams.stencilClearValue = stencil;
252
253 return clear(state, clearParams);
254}
255
Geoff Langbce529e2014-12-01 12:48:41 -0500256GLenum FramebufferD3D::getImplementationColorReadFormat() const
257{
Jamie Madill7147f012015-03-05 15:41:40 -0500258 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500259
Jamie Madillb885e572015-02-03 16:16:04 -0500260 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500261 {
262 return GL_NONE;
263 }
264
Geoff Langc2e75af2015-01-05 14:26:24 -0500265 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500266 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500267 if (error.isError())
268 {
269 return GL_NONE;
270 }
Geoff Langbce529e2014-12-01 12:48:41 -0500271
Geoff Langd8a22582014-12-17 15:28:23 -0500272 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
273 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
274
275 return implementationFormatInfo.format;
Geoff Langbce529e2014-12-01 12:48:41 -0500276}
277
278GLenum FramebufferD3D::getImplementationColorReadType() const
279{
Jamie Madill7147f012015-03-05 15:41:40 -0500280 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500281
Jamie Madillb885e572015-02-03 16:16:04 -0500282 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500283 {
284 return GL_NONE;
285 }
286
Geoff Langc2e75af2015-01-05 14:26:24 -0500287 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500288 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500289 if (error.isError())
290 {
291 return GL_NONE;
292 }
Geoff Langbce529e2014-12-01 12:48:41 -0500293
Geoff Langd8a22582014-12-17 15:28:23 -0500294 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
295 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
296
297 return implementationFormatInfo.type;
Geoff Langbce529e2014-12-01 12:48:41 -0500298}
299
300gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
301{
302 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
303 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Minmin Gongb8aee3b2015-01-27 14:42:36 -0800304 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment(), 0);
Geoff Langbce529e2014-12-01 12:48:41 -0500305
306 return readPixels(area, format, type, outputPitch, state.getPackState(), reinterpret_cast<uint8_t*>(pixels));
307}
308
Geoff Lang54bd5a42014-12-01 12:51:04 -0500309gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
310 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
311{
312 bool blitRenderTarget = false;
313 if ((mask & GL_COLOR_BUFFER_BIT) &&
314 sourceFramebuffer->getReadColorbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500315 mData.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500316 {
317 blitRenderTarget = true;
318 }
319
320 bool blitStencil = false;
321 if ((mask & GL_STENCIL_BUFFER_BIT) &&
322 sourceFramebuffer->getStencilbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500323 mData.mStencilAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500324 {
325 blitStencil = true;
326 }
327
328 bool blitDepth = false;
329 if ((mask & GL_DEPTH_BUFFER_BIT) &&
330 sourceFramebuffer->getDepthbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500331 mData.mDepthAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500332 {
333 blitDepth = true;
334 }
335
336 if (blitRenderTarget || blitDepth || blitStencil)
337 {
338 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
339 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
340 filter, sourceFramebuffer);
341 if (error.isError())
342 {
343 return error;
344 }
345 }
346
347 return gl::Error(GL_NO_ERROR);
348}
349
Geoff Lang748f74e2014-12-01 11:25:34 -0500350GLenum FramebufferD3D::checkStatus() const
351{
352 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madill7147f012015-03-05 15:41:40 -0500353 for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500354 {
Jamie Madill7147f012015-03-05 15:41:40 -0500355 const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500356 if (attachment != nullptr)
357 {
358 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
359 {
Jamie Madill7147f012015-03-05 15:41:40 -0500360 const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500361 if (prevAttachment != nullptr &&
362 (attachment->id() == prevAttachment->id() &&
363 attachment->type() == prevAttachment->type()))
364 {
365 return GL_FRAMEBUFFER_UNSUPPORTED;
366 }
367 }
368 }
369 }
370
371 return GL_FRAMEBUFFER_COMPLETE;
372}
373
Jamie Madill7147f012015-03-05 15:41:40 -0500374const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const
375{
Jamie Madill85a18042015-03-05 15:41:41 -0500376 if (!workarounds.mrtPerfWorkaround)
377 {
378 return mData.mColorAttachments;
379 }
380
381 if (!mInvalidateColorAttachmentCache)
382 {
383 return mColorAttachmentsForRender;
384 }
385
Jamie Madill7147f012015-03-05 15:41:40 -0500386 // Does not actually free memory
387 mColorAttachmentsForRender.clear();
388
389 for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex)
390 {
391 GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex];
392 gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex];
393
394 if (colorAttachment != nullptr && drawBufferState != GL_NONE)
395 {
396 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
397 mColorAttachmentsForRender.push_back(colorAttachment);
398 }
Jamie Madill7147f012015-03-05 15:41:40 -0500399 }
400
Jamie Madill85a18042015-03-05 15:41:41 -0500401 mInvalidateColorAttachmentCache = false;
Jamie Madill7147f012015-03-05 15:41:40 -0500402 return mColorAttachmentsForRender;
403}
404
Geoff Langc2e75af2015-01-05 14:26:24 -0500405gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT)
Geoff Langb5d8f232014-12-04 15:43:01 -0500406{
407 if (attachment->type() == GL_TEXTURE)
408 {
409 gl::Texture *texture = attachment->getTexture();
410 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500411 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500412 const gl::ImageIndex *index = attachment->getTextureImageIndex();
413 ASSERT(index);
414 return textureD3D->getRenderTarget(*index, outRT);
415 }
416 else if (attachment->type() == GL_RENDERBUFFER)
417 {
418 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
419 ASSERT(renderbuffer);
420 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
421 *outRT = renderbufferD3D->getRenderTarget();
422 return gl::Error(GL_NO_ERROR);
423 }
424 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
425 {
426 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
427 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
428 ASSERT(defaultAttachmentD3D);
429
430 *outRT = defaultAttachmentD3D->getRenderTarget();
431 return gl::Error(GL_NO_ERROR);
432 }
433 else
434 {
435 UNREACHABLE();
436 return gl::Error(GL_INVALID_OPERATION);
437 }
438}
439
440// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
441unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
442{
443 if (attachment->type() == GL_TEXTURE)
444 {
445 gl::Texture *texture = attachment->getTexture();
446 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500447 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500448 const gl::ImageIndex *index = attachment->getTextureImageIndex();
449 ASSERT(index);
450 return textureD3D->getRenderTargetSerial(*index);
451 }
452 else if (attachment->type() == GL_RENDERBUFFER)
453 {
454 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
455 ASSERT(renderbuffer);
456 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
457 return renderbufferD3D->getRenderTargetSerial();
458 }
459 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
460 {
461 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
462 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
463 ASSERT(defaultAttachmentD3D);
464 return defaultAttachmentD3D->getRenderTarget()->getSerial();
465 }
466 else
467 {
468 UNREACHABLE();
469 return 0;
470 }
471}
472
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500473}