blob: ad3153c3aafd7e1b984097766c0f8005b8e88783 [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
Geoff Langc2e75af2015-01-05 14:26:24 -050021DefaultAttachmentD3D::DefaultAttachmentD3D(RenderTargetD3D *renderTarget)
Geoff Lang6a1e6b92014-11-06 10:42:45 -050022 : mRenderTarget(renderTarget)
23{
24 ASSERT(mRenderTarget);
25}
26
27DefaultAttachmentD3D::~DefaultAttachmentD3D()
28{
29 SafeDelete(mRenderTarget);
30}
31
32DefaultAttachmentD3D *DefaultAttachmentD3D::makeDefaultAttachmentD3D(DefaultAttachmentImpl* impl)
33{
34 ASSERT(HAS_DYNAMIC_TYPE(DefaultAttachmentD3D*, impl));
35 return static_cast<DefaultAttachmentD3D*>(impl);
36}
37
38GLsizei DefaultAttachmentD3D::getWidth() const
39{
40 return mRenderTarget->getWidth();
41}
42
43GLsizei DefaultAttachmentD3D::getHeight() const
44{
45 return mRenderTarget->getHeight();
46}
47
48GLenum DefaultAttachmentD3D::getInternalFormat() const
49{
50 return mRenderTarget->getInternalFormat();
51}
52
Geoff Lang6a1e6b92014-11-06 10:42:45 -050053GLsizei DefaultAttachmentD3D::getSamples() const
54{
55 return mRenderTarget->getSamples();
56}
57
Geoff Langc2e75af2015-01-05 14:26:24 -050058RenderTargetD3D *DefaultAttachmentD3D::getRenderTarget() const
Geoff Lang6a1e6b92014-11-06 10:42:45 -050059{
60 return mRenderTarget;
61}
62
Jamie Madilld1405e52015-03-05 15:41:39 -050063FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
64 : FramebufferImpl(data),
65 mRenderer(renderer),
Jamie Madill85a18042015-03-05 15:41:41 -050066 mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr),
67 mInvalidateColorAttachmentCache(true)
Geoff Langda88add2014-12-01 10:22:01 -050068{
69 ASSERT(mRenderer != nullptr);
70}
71
72FramebufferD3D::~FramebufferD3D()
73{
74}
75
Jamie Madill7147f012015-03-05 15:41:40 -050076void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050077{
Jamie Madill85a18042015-03-05 15:41:41 -050078 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -050079}
80
Jamie Madillf90353e2015-03-05 19:37:58 -050081void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050082{
83}
84
Jamie Madill7147f012015-03-05 15:41:40 -050085void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050086{
87}
88
Jamie Madill7147f012015-03-05 15:41:40 -050089void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *)
Geoff Lang9dd95802014-12-01 11:12:59 -050090{
91}
92
Jamie Madill7147f012015-03-05 15:41:40 -050093void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
Geoff Lang9dd95802014-12-01 11:12:59 -050094{
Jamie Madill85a18042015-03-05 15:41:41 -050095 mInvalidateColorAttachmentCache = true;
Geoff Lang9dd95802014-12-01 11:12:59 -050096}
97
Jamie Madill7147f012015-03-05 15:41:40 -050098void FramebufferD3D::setReadBuffer(GLenum)
Geoff Lang9dd95802014-12-01 11:12:59 -050099{
100}
101
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500102gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
103{
104 // No-op in D3D
105 return gl::Error(GL_NO_ERROR);
106}
107
108gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
109{
110 // No-op in D3D
111 return gl::Error(GL_NO_ERROR);
112}
113
Geoff Langb04dc822014-12-01 12:02:02 -0500114gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
115{
116 gl::ClearParameters clearParams = state.getClearParameters(mask);
117 return clear(state, clearParams);
118}
119
120gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
121{
122 // glClearBufferfv can be called to clear the color buffer or depth buffer
123 gl::ClearParameters clearParams = state.getClearParameters(0);
124
125 if (buffer == GL_COLOR)
126 {
127 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
128 {
129 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
130 }
131 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
132 clearParams.colorClearType = GL_FLOAT;
133 }
134
135 if (buffer == GL_DEPTH)
136 {
137 clearParams.clearDepth = true;
138 clearParams.depthClearValue = values[0];
139 }
140
141 return clear(state, clearParams);
142}
143
144gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
145{
146 // glClearBufferuiv can only be called to clear a color buffer
147 gl::ClearParameters clearParams = state.getClearParameters(0);
148 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
149 {
150 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
151 }
152 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
153 clearParams.colorClearType = GL_UNSIGNED_INT;
154
155 return clear(state, clearParams);
156}
157
158gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
159{
160 // glClearBufferiv can be called to clear the color buffer or stencil buffer
161 gl::ClearParameters clearParams = state.getClearParameters(0);
162
163 if (buffer == GL_COLOR)
164 {
165 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
166 {
167 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
168 }
169 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
170 clearParams.colorClearType = GL_INT;
171 }
172
173 if (buffer == GL_STENCIL)
174 {
175 clearParams.clearStencil = true;
176 clearParams.stencilClearValue = values[1];
177 }
178
179 return clear(state, clearParams);
180}
181
182gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
183{
184 // glClearBufferfi can only be called to clear a depth stencil buffer
185 gl::ClearParameters clearParams = state.getClearParameters(0);
186 clearParams.clearDepth = true;
187 clearParams.depthClearValue = depth;
188 clearParams.clearStencil = true;
189 clearParams.stencilClearValue = stencil;
190
191 return clear(state, clearParams);
192}
193
Geoff Langbce529e2014-12-01 12:48:41 -0500194GLenum FramebufferD3D::getImplementationColorReadFormat() const
195{
Jamie Madill7147f012015-03-05 15:41:40 -0500196 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500197
Jamie Madillb885e572015-02-03 16:16:04 -0500198 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500199 {
200 return GL_NONE;
201 }
202
Geoff Langc2e75af2015-01-05 14:26:24 -0500203 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500204 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500205 if (error.isError())
206 {
207 return GL_NONE;
208 }
Geoff Langbce529e2014-12-01 12:48:41 -0500209
Geoff Langd8a22582014-12-17 15:28:23 -0500210 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
211 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
212
213 return implementationFormatInfo.format;
Geoff Langbce529e2014-12-01 12:48:41 -0500214}
215
216GLenum FramebufferD3D::getImplementationColorReadType() const
217{
Jamie Madill7147f012015-03-05 15:41:40 -0500218 const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
Geoff Langbce529e2014-12-01 12:48:41 -0500219
Jamie Madillb885e572015-02-03 16:16:04 -0500220 if (readAttachment == nullptr)
Geoff Langbce529e2014-12-01 12:48:41 -0500221 {
222 return GL_NONE;
223 }
224
Geoff Langc2e75af2015-01-05 14:26:24 -0500225 RenderTargetD3D *attachmentRenderTarget = NULL;
Jamie Madillb885e572015-02-03 16:16:04 -0500226 gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
Geoff Langd8a22582014-12-17 15:28:23 -0500227 if (error.isError())
228 {
229 return GL_NONE;
230 }
Geoff Langbce529e2014-12-01 12:48:41 -0500231
Geoff Langd8a22582014-12-17 15:28:23 -0500232 GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
233 const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
234
235 return implementationFormatInfo.type;
Geoff Langbce529e2014-12-01 12:48:41 -0500236}
237
238gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
239{
240 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
241 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Minmin Gongb8aee3b2015-01-27 14:42:36 -0800242 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment(), 0);
Geoff Langbce529e2014-12-01 12:48:41 -0500243
244 return readPixels(area, format, type, outputPitch, state.getPackState(), reinterpret_cast<uint8_t*>(pixels));
245}
246
Geoff Lang54bd5a42014-12-01 12:51:04 -0500247gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
248 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
249{
250 bool blitRenderTarget = false;
251 if ((mask & GL_COLOR_BUFFER_BIT) &&
252 sourceFramebuffer->getReadColorbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500253 mData.getFirstColorAttachment() != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500254 {
255 blitRenderTarget = true;
256 }
257
258 bool blitStencil = false;
259 if ((mask & GL_STENCIL_BUFFER_BIT) &&
260 sourceFramebuffer->getStencilbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500261 mData.mStencilAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500262 {
263 blitStencil = true;
264 }
265
266 bool blitDepth = false;
267 if ((mask & GL_DEPTH_BUFFER_BIT) &&
268 sourceFramebuffer->getDepthbuffer() != nullptr &&
Jamie Madill7147f012015-03-05 15:41:40 -0500269 mData.mDepthAttachment != nullptr)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500270 {
271 blitDepth = true;
272 }
273
274 if (blitRenderTarget || blitDepth || blitStencil)
275 {
276 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
277 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
278 filter, sourceFramebuffer);
279 if (error.isError())
280 {
281 return error;
282 }
283 }
284
285 return gl::Error(GL_NO_ERROR);
286}
287
Geoff Lang748f74e2014-12-01 11:25:34 -0500288GLenum FramebufferD3D::checkStatus() const
289{
290 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
Jamie Madill7147f012015-03-05 15:41:40 -0500291 for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++)
Geoff Lang748f74e2014-12-01 11:25:34 -0500292 {
Jamie Madill7147f012015-03-05 15:41:40 -0500293 const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500294 if (attachment != nullptr)
295 {
296 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
297 {
Jamie Madill7147f012015-03-05 15:41:40 -0500298 const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment];
Geoff Lang748f74e2014-12-01 11:25:34 -0500299 if (prevAttachment != nullptr &&
300 (attachment->id() == prevAttachment->id() &&
301 attachment->type() == prevAttachment->type()))
302 {
303 return GL_FRAMEBUFFER_UNSUPPORTED;
304 }
305 }
306 }
307 }
308
309 return GL_FRAMEBUFFER_COMPLETE;
310}
311
Jamie Madill7147f012015-03-05 15:41:40 -0500312const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const
313{
Jamie Madill85a18042015-03-05 15:41:41 -0500314 if (!workarounds.mrtPerfWorkaround)
315 {
316 return mData.mColorAttachments;
317 }
318
319 if (!mInvalidateColorAttachmentCache)
320 {
321 return mColorAttachmentsForRender;
322 }
323
Jamie Madill7147f012015-03-05 15:41:40 -0500324 // Does not actually free memory
325 mColorAttachmentsForRender.clear();
326
327 for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex)
328 {
329 GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex];
330 gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex];
331
332 if (colorAttachment != nullptr && drawBufferState != GL_NONE)
333 {
334 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
335 mColorAttachmentsForRender.push_back(colorAttachment);
336 }
Jamie Madill7147f012015-03-05 15:41:40 -0500337 }
338
Jamie Madill85a18042015-03-05 15:41:41 -0500339 mInvalidateColorAttachmentCache = false;
Jamie Madill7147f012015-03-05 15:41:40 -0500340 return mColorAttachmentsForRender;
341}
342
Geoff Langc2e75af2015-01-05 14:26:24 -0500343gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT)
Geoff Langb5d8f232014-12-04 15:43:01 -0500344{
345 if (attachment->type() == GL_TEXTURE)
346 {
347 gl::Texture *texture = attachment->getTexture();
348 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500349 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500350 const gl::ImageIndex *index = attachment->getTextureImageIndex();
351 ASSERT(index);
352 return textureD3D->getRenderTarget(*index, outRT);
353 }
354 else if (attachment->type() == GL_RENDERBUFFER)
355 {
356 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
357 ASSERT(renderbuffer);
358 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
359 *outRT = renderbufferD3D->getRenderTarget();
360 return gl::Error(GL_NO_ERROR);
361 }
362 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
363 {
364 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
365 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
366 ASSERT(defaultAttachmentD3D);
367
368 *outRT = defaultAttachmentD3D->getRenderTarget();
369 return gl::Error(GL_NO_ERROR);
370 }
371 else
372 {
373 UNREACHABLE();
374 return gl::Error(GL_INVALID_OPERATION);
375 }
376}
377
378// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
379unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
380{
381 if (attachment->type() == GL_TEXTURE)
382 {
383 gl::Texture *texture = attachment->getTexture();
384 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500385 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500386 const gl::ImageIndex *index = attachment->getTextureImageIndex();
387 ASSERT(index);
388 return textureD3D->getRenderTargetSerial(*index);
389 }
390 else if (attachment->type() == GL_RENDERBUFFER)
391 {
392 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
393 ASSERT(renderbuffer);
394 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
395 return renderbufferD3D->getRenderTargetSerial();
396 }
397 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
398 {
399 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
400 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
401 ASSERT(defaultAttachmentD3D);
402 return defaultAttachmentD3D->getRenderTarget()->getSerial();
403 }
404 else
405 {
406 UNREACHABLE();
407 return 0;
408 }
409}
410
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500411}