blob: 5a3c00666dd825512b57f48e3db1312d6aa9d41b [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
Geoff Langda88add2014-12-01 10:22:01 -050063
Jamie Madilld1405e52015-03-05 15:41:39 -050064FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
65 : FramebufferImpl(data),
66 mRenderer(renderer),
Geoff Langb04dc822014-12-01 12:02:02 -050067 mColorBuffers(renderer->getRendererCaps().maxColorAttachments),
68 mDepthbuffer(nullptr),
69 mStencilbuffer(nullptr),
Geoff Langbce529e2014-12-01 12:48:41 -050070 mDrawBuffers(renderer->getRendererCaps().maxDrawBuffers),
71 mReadBuffer(GL_COLOR_ATTACHMENT0)
Geoff Langda88add2014-12-01 10:22:01 -050072{
73 ASSERT(mRenderer != nullptr);
Geoff Lang748f74e2014-12-01 11:25:34 -050074
75 std::fill(mColorBuffers.begin(), mColorBuffers.end(), nullptr);
Geoff Langb04dc822014-12-01 12:02:02 -050076
77 ASSERT(mDrawBuffers.size() > 0);
78 mDrawBuffers[0] = GL_COLOR_ATTACHMENT0;
79 std::fill(mDrawBuffers.begin() + 1, mDrawBuffers.end(), GL_NONE);
Geoff Langda88add2014-12-01 10:22:01 -050080}
81
82FramebufferD3D::~FramebufferD3D()
83{
84}
85
Geoff Lang9dd95802014-12-01 11:12:59 -050086void FramebufferD3D::setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment)
87{
Geoff Lang748f74e2014-12-01 11:25:34 -050088 ASSERT(index < mColorBuffers.size());
89 mColorBuffers[index] = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050090}
91
92void FramebufferD3D::setDepthttachment(const gl::FramebufferAttachment *attachment)
93{
Geoff Langb04dc822014-12-01 12:02:02 -050094 mDepthbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050095}
96
97void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *attachment)
98{
Geoff Langb04dc822014-12-01 12:02:02 -050099 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500100}
101
102void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *attachment)
103{
Geoff Langb04dc822014-12-01 12:02:02 -0500104 mDepthbuffer = attachment;
105 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500106}
107
108void FramebufferD3D::setDrawBuffers(size_t count, const GLenum *buffers)
109{
Geoff Langb04dc822014-12-01 12:02:02 -0500110 std::copy_n(buffers, count, mDrawBuffers.begin());
111 std::fill(mDrawBuffers.begin() + count, mDrawBuffers.end(), GL_NONE);
Geoff Lang9dd95802014-12-01 11:12:59 -0500112}
113
114void FramebufferD3D::setReadBuffer(GLenum buffer)
115{
Geoff Langbce529e2014-12-01 12:48:41 -0500116 mReadBuffer = buffer;
Geoff Lang9dd95802014-12-01 11:12:59 -0500117}
118
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500119gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
120{
121 // No-op in D3D
122 return gl::Error(GL_NO_ERROR);
123}
124
125gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
126{
127 // No-op in D3D
128 return gl::Error(GL_NO_ERROR);
129}
130
Geoff Langb04dc822014-12-01 12:02:02 -0500131gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
132{
133 gl::ClearParameters clearParams = state.getClearParameters(mask);
134 return clear(state, clearParams);
135}
136
137gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
138{
139 // glClearBufferfv can be called to clear the color buffer or depth buffer
140 gl::ClearParameters clearParams = state.getClearParameters(0);
141
142 if (buffer == GL_COLOR)
143 {
144 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
145 {
146 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
147 }
148 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
149 clearParams.colorClearType = GL_FLOAT;
150 }
151
152 if (buffer == GL_DEPTH)
153 {
154 clearParams.clearDepth = true;
155 clearParams.depthClearValue = values[0];
156 }
157
158 return clear(state, clearParams);
159}
160
161gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
162{
163 // glClearBufferuiv can only be called to clear a color buffer
164 gl::ClearParameters clearParams = state.getClearParameters(0);
165 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
172 return clear(state, clearParams);
173}
174
175gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
176{
177 // glClearBufferiv can be called to clear the color buffer or stencil buffer
178 gl::ClearParameters clearParams = state.getClearParameters(0);
179
180 if (buffer == GL_COLOR)
181 {
182 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
183 {
184 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
185 }
186 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
187 clearParams.colorClearType = GL_INT;
188 }
189
190 if (buffer == GL_STENCIL)
191 {
192 clearParams.clearStencil = true;
193 clearParams.stencilClearValue = values[1];
194 }
195
196 return clear(state, clearParams);
197}
198
199gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
200{
201 // glClearBufferfi can only be called to clear a depth stencil buffer
202 gl::ClearParameters clearParams = state.getClearParameters(0);
203 clearParams.clearDepth = true;
204 clearParams.depthClearValue = depth;
205 clearParams.clearStencil = true;
206 clearParams.stencilClearValue = stencil;
207
208 return clear(state, clearParams);
209}
210
Jamie Madillb885e572015-02-03 16:16:04 -0500211const gl::FramebufferAttachment *FramebufferD3D::getReadAttachment() const
212{
213 ASSERT(mReadBuffer == GL_BACK || (mReadBuffer >= GL_COLOR_ATTACHMENT0 && mReadBuffer <= GL_COLOR_ATTACHMENT15));
214 size_t readIndex = (mReadBuffer == GL_BACK ? 0 : static_cast<size_t>(mReadBuffer - GL_COLOR_ATTACHMENT0));
215 ASSERT(readIndex < mColorBuffers.size());
216 return mColorBuffers[readIndex];
217}
218
Geoff Langbce529e2014-12-01 12:48:41 -0500219GLenum FramebufferD3D::getImplementationColorReadFormat() const
220{
Jamie Madillb885e572015-02-03 16:16:04 -0500221 const gl::FramebufferAttachment *readAttachment = 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 Madillb885e572015-02-03 16:16:04 -0500229 gl::Error error = GetAttachmentRenderTarget(readAttachment, &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 Madillb885e572015-02-03 16:16:04 -0500243 const gl::FramebufferAttachment *readAttachment = 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 Madillb885e572015-02-03 16:16:04 -0500251 gl::Error error = GetAttachmentRenderTarget(readAttachment, &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{
265 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
266 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
Minmin Gongb8aee3b2015-01-27 14:42:36 -0800267 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment(), 0);
Geoff Langbce529e2014-12-01 12:48:41 -0500268
269 return readPixels(area, format, type, outputPitch, state.getPackState(), reinterpret_cast<uint8_t*>(pixels));
270}
271
Geoff Lang54bd5a42014-12-01 12:51:04 -0500272gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
273 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
274{
275 bool blitRenderTarget = false;
276 if ((mask & GL_COLOR_BUFFER_BIT) &&
277 sourceFramebuffer->getReadColorbuffer() != nullptr &&
278 std::any_of(mColorBuffers.begin(), mColorBuffers.end(), [](const gl::FramebufferAttachment* attachment){ return attachment != nullptr; }))
279 {
280 blitRenderTarget = true;
281 }
282
283 bool blitStencil = false;
284 if ((mask & GL_STENCIL_BUFFER_BIT) &&
285 sourceFramebuffer->getStencilbuffer() != nullptr &&
286 mStencilbuffer != nullptr)
287 {
288 blitStencil = true;
289 }
290
291 bool blitDepth = false;
292 if ((mask & GL_DEPTH_BUFFER_BIT) &&
293 sourceFramebuffer->getDepthbuffer() != nullptr &&
294 mDepthbuffer != nullptr)
295 {
296 blitDepth = true;
297 }
298
299 if (blitRenderTarget || blitDepth || blitStencil)
300 {
301 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
302 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
303 filter, sourceFramebuffer);
304 if (error.isError())
305 {
306 return error;
307 }
308 }
309
310 return gl::Error(GL_NO_ERROR);
311}
312
Geoff Lang748f74e2014-12-01 11:25:34 -0500313GLenum FramebufferD3D::checkStatus() const
314{
315 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
316 for (size_t colorAttachment = 0; colorAttachment < mColorBuffers.size(); colorAttachment++)
317 {
318 const gl::FramebufferAttachment *attachment = mColorBuffers[colorAttachment];
319 if (attachment != nullptr)
320 {
321 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
322 {
323 const gl::FramebufferAttachment *prevAttachment = mColorBuffers[prevColorAttachment];
324 if (prevAttachment != nullptr &&
325 (attachment->id() == prevAttachment->id() &&
326 attachment->type() == prevAttachment->type()))
327 {
328 return GL_FRAMEBUFFER_UNSUPPORTED;
329 }
330 }
331 }
332 }
333
334 return GL_FRAMEBUFFER_COMPLETE;
335}
336
Geoff Langc2e75af2015-01-05 14:26:24 -0500337gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT)
Geoff Langb5d8f232014-12-04 15:43:01 -0500338{
339 if (attachment->type() == GL_TEXTURE)
340 {
341 gl::Texture *texture = attachment->getTexture();
342 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500343 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500344 const gl::ImageIndex *index = attachment->getTextureImageIndex();
345 ASSERT(index);
346 return textureD3D->getRenderTarget(*index, outRT);
347 }
348 else if (attachment->type() == GL_RENDERBUFFER)
349 {
350 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
351 ASSERT(renderbuffer);
352 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
353 *outRT = renderbufferD3D->getRenderTarget();
354 return gl::Error(GL_NO_ERROR);
355 }
356 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
357 {
358 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
359 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
360 ASSERT(defaultAttachmentD3D);
361
362 *outRT = defaultAttachmentD3D->getRenderTarget();
363 return gl::Error(GL_NO_ERROR);
364 }
365 else
366 {
367 UNREACHABLE();
368 return gl::Error(GL_INVALID_OPERATION);
369 }
370}
371
372// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
373unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
374{
375 if (attachment->type() == GL_TEXTURE)
376 {
377 gl::Texture *texture = attachment->getTexture();
378 ASSERT(texture);
Jamie Madill9236b412015-02-02 16:51:52 -0500379 TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
Geoff Langb5d8f232014-12-04 15:43:01 -0500380 const gl::ImageIndex *index = attachment->getTextureImageIndex();
381 ASSERT(index);
382 return textureD3D->getRenderTargetSerial(*index);
383 }
384 else if (attachment->type() == GL_RENDERBUFFER)
385 {
386 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
387 ASSERT(renderbuffer);
388 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
389 return renderbufferD3D->getRenderTargetSerial();
390 }
391 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
392 {
393 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
394 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
395 ASSERT(defaultAttachmentD3D);
396 return defaultAttachmentD3D->getRenderTarget()->getSerial();
397 }
398 else
399 {
400 UNREACHABLE();
401 return 0;
402 }
403}
404
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500405}