blob: 3ca5d14f9848b5ca7aa45a8f78167a5644990686 [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 Langb5d8f232014-12-04 15:43:01 -050012#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/renderer/RenderTarget.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
21DefaultAttachmentD3D::DefaultAttachmentD3D(RenderTarget *renderTarget)
22 : 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
53GLenum DefaultAttachmentD3D::getActualFormat() const
54{
55 return mRenderTarget->getActualFormat();
56}
57
58GLsizei DefaultAttachmentD3D::getSamples() const
59{
60 return mRenderTarget->getSamples();
61}
62
63RenderTarget *DefaultAttachmentD3D::getRenderTarget() const
64{
65 return mRenderTarget;
66}
67
Geoff Langda88add2014-12-01 10:22:01 -050068
69FramebufferD3D::FramebufferD3D(RendererD3D *renderer)
Geoff Lang748f74e2014-12-01 11:25:34 -050070 : mRenderer(renderer),
Geoff Langb04dc822014-12-01 12:02:02 -050071 mColorBuffers(renderer->getRendererCaps().maxColorAttachments),
72 mDepthbuffer(nullptr),
73 mStencilbuffer(nullptr),
Geoff Langbce529e2014-12-01 12:48:41 -050074 mDrawBuffers(renderer->getRendererCaps().maxDrawBuffers),
75 mReadBuffer(GL_COLOR_ATTACHMENT0)
Geoff Langda88add2014-12-01 10:22:01 -050076{
77 ASSERT(mRenderer != nullptr);
Geoff Lang748f74e2014-12-01 11:25:34 -050078
79 std::fill(mColorBuffers.begin(), mColorBuffers.end(), nullptr);
Geoff Langb04dc822014-12-01 12:02:02 -050080
81 ASSERT(mDrawBuffers.size() > 0);
82 mDrawBuffers[0] = GL_COLOR_ATTACHMENT0;
83 std::fill(mDrawBuffers.begin() + 1, mDrawBuffers.end(), GL_NONE);
Geoff Langda88add2014-12-01 10:22:01 -050084}
85
86FramebufferD3D::~FramebufferD3D()
87{
88}
89
Geoff Lang9dd95802014-12-01 11:12:59 -050090void FramebufferD3D::setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment)
91{
Geoff Lang748f74e2014-12-01 11:25:34 -050092 ASSERT(index < mColorBuffers.size());
93 mColorBuffers[index] = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050094}
95
96void FramebufferD3D::setDepthttachment(const gl::FramebufferAttachment *attachment)
97{
Geoff Langb04dc822014-12-01 12:02:02 -050098 mDepthbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050099}
100
101void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *attachment)
102{
Geoff Langb04dc822014-12-01 12:02:02 -0500103 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500104}
105
106void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *attachment)
107{
Geoff Langb04dc822014-12-01 12:02:02 -0500108 mDepthbuffer = attachment;
109 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500110}
111
112void FramebufferD3D::setDrawBuffers(size_t count, const GLenum *buffers)
113{
Geoff Langb04dc822014-12-01 12:02:02 -0500114 std::copy_n(buffers, count, mDrawBuffers.begin());
115 std::fill(mDrawBuffers.begin() + count, mDrawBuffers.end(), GL_NONE);
Geoff Lang9dd95802014-12-01 11:12:59 -0500116}
117
118void FramebufferD3D::setReadBuffer(GLenum buffer)
119{
Geoff Langbce529e2014-12-01 12:48:41 -0500120 mReadBuffer = buffer;
Geoff Lang9dd95802014-12-01 11:12:59 -0500121}
122
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500123gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
124{
125 // No-op in D3D
126 return gl::Error(GL_NO_ERROR);
127}
128
129gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
130{
131 // No-op in D3D
132 return gl::Error(GL_NO_ERROR);
133}
134
Geoff Langb04dc822014-12-01 12:02:02 -0500135gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
136{
137 gl::ClearParameters clearParams = state.getClearParameters(mask);
138 return clear(state, clearParams);
139}
140
141gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
142{
143 // glClearBufferfv can be called to clear the color buffer or depth buffer
144 gl::ClearParameters clearParams = state.getClearParameters(0);
145
146 if (buffer == GL_COLOR)
147 {
148 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
149 {
150 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
151 }
152 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
153 clearParams.colorClearType = GL_FLOAT;
154 }
155
156 if (buffer == GL_DEPTH)
157 {
158 clearParams.clearDepth = true;
159 clearParams.depthClearValue = values[0];
160 }
161
162 return clear(state, clearParams);
163}
164
165gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
166{
167 // glClearBufferuiv can only be called to clear a color buffer
168 gl::ClearParameters clearParams = state.getClearParameters(0);
169 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
170 {
171 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
172 }
173 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
174 clearParams.colorClearType = GL_UNSIGNED_INT;
175
176 return clear(state, clearParams);
177}
178
179gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
180{
181 // glClearBufferiv can be called to clear the color buffer or stencil buffer
182 gl::ClearParameters clearParams = state.getClearParameters(0);
183
184 if (buffer == GL_COLOR)
185 {
186 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
187 {
188 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
189 }
190 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
191 clearParams.colorClearType = GL_INT;
192 }
193
194 if (buffer == GL_STENCIL)
195 {
196 clearParams.clearStencil = true;
197 clearParams.stencilClearValue = values[1];
198 }
199
200 return clear(state, clearParams);
201}
202
203gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
204{
205 // glClearBufferfi can only be called to clear a depth stencil buffer
206 gl::ClearParameters clearParams = state.getClearParameters(0);
207 clearParams.clearDepth = true;
208 clearParams.depthClearValue = depth;
209 clearParams.clearStencil = true;
210 clearParams.stencilClearValue = stencil;
211
212 return clear(state, clearParams);
213}
214
Geoff Langbce529e2014-12-01 12:48:41 -0500215GLenum FramebufferD3D::getImplementationColorReadFormat() const
216{
217 // Will require more logic if glReadBuffers is supported
218 ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
219
220 if (mColorBuffers[0] == nullptr)
221 {
222 return GL_NONE;
223 }
224
225 GLenum actualFormat = mColorBuffers[0]->getActualFormat();
226 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualFormat);
227
228 return actualFormatInfo.format;
229}
230
231GLenum FramebufferD3D::getImplementationColorReadType() const
232{
233 // Will require more logic if glReadBuffers is supported
234 ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
235
236 if (mColorBuffers[0] == nullptr)
237 {
238 return GL_NONE;
239 }
240
241 GLenum actualFormat = mColorBuffers[0]->getActualFormat();
242 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualFormat);
243
244 return actualFormatInfo.type;
245}
246
247gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
248{
249 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
250 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
251 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment());
252
253 return readPixels(area, format, type, outputPitch, state.getPackState(), reinterpret_cast<uint8_t*>(pixels));
254}
255
Geoff Lang54bd5a42014-12-01 12:51:04 -0500256gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
257 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
258{
259 bool blitRenderTarget = false;
260 if ((mask & GL_COLOR_BUFFER_BIT) &&
261 sourceFramebuffer->getReadColorbuffer() != nullptr &&
262 std::any_of(mColorBuffers.begin(), mColorBuffers.end(), [](const gl::FramebufferAttachment* attachment){ return attachment != nullptr; }))
263 {
264 blitRenderTarget = true;
265 }
266
267 bool blitStencil = false;
268 if ((mask & GL_STENCIL_BUFFER_BIT) &&
269 sourceFramebuffer->getStencilbuffer() != nullptr &&
270 mStencilbuffer != nullptr)
271 {
272 blitStencil = true;
273 }
274
275 bool blitDepth = false;
276 if ((mask & GL_DEPTH_BUFFER_BIT) &&
277 sourceFramebuffer->getDepthbuffer() != nullptr &&
278 mDepthbuffer != nullptr)
279 {
280 blitDepth = true;
281 }
282
283 if (blitRenderTarget || blitDepth || blitStencil)
284 {
285 const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
286 gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
287 filter, sourceFramebuffer);
288 if (error.isError())
289 {
290 return error;
291 }
292 }
293
294 return gl::Error(GL_NO_ERROR);
295}
296
Geoff Lang748f74e2014-12-01 11:25:34 -0500297GLenum FramebufferD3D::checkStatus() const
298{
299 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
300 for (size_t colorAttachment = 0; colorAttachment < mColorBuffers.size(); colorAttachment++)
301 {
302 const gl::FramebufferAttachment *attachment = mColorBuffers[colorAttachment];
303 if (attachment != nullptr)
304 {
305 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
306 {
307 const gl::FramebufferAttachment *prevAttachment = mColorBuffers[prevColorAttachment];
308 if (prevAttachment != nullptr &&
309 (attachment->id() == prevAttachment->id() &&
310 attachment->type() == prevAttachment->type()))
311 {
312 return GL_FRAMEBUFFER_UNSUPPORTED;
313 }
314 }
315 }
316 }
317
318 return GL_FRAMEBUFFER_COMPLETE;
319}
320
Geoff Langb5d8f232014-12-04 15:43:01 -0500321gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget **outRT)
322{
323 if (attachment->type() == GL_TEXTURE)
324 {
325 gl::Texture *texture = attachment->getTexture();
326 ASSERT(texture);
327 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
328 const gl::ImageIndex *index = attachment->getTextureImageIndex();
329 ASSERT(index);
330 return textureD3D->getRenderTarget(*index, outRT);
331 }
332 else if (attachment->type() == GL_RENDERBUFFER)
333 {
334 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
335 ASSERT(renderbuffer);
336 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
337 *outRT = renderbufferD3D->getRenderTarget();
338 return gl::Error(GL_NO_ERROR);
339 }
340 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
341 {
342 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
343 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
344 ASSERT(defaultAttachmentD3D);
345
346 *outRT = defaultAttachmentD3D->getRenderTarget();
347 return gl::Error(GL_NO_ERROR);
348 }
349 else
350 {
351 UNREACHABLE();
352 return gl::Error(GL_INVALID_OPERATION);
353 }
354}
355
356// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
357unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
358{
359 if (attachment->type() == GL_TEXTURE)
360 {
361 gl::Texture *texture = attachment->getTexture();
362 ASSERT(texture);
363 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
364 const gl::ImageIndex *index = attachment->getTextureImageIndex();
365 ASSERT(index);
366 return textureD3D->getRenderTargetSerial(*index);
367 }
368 else if (attachment->type() == GL_RENDERBUFFER)
369 {
370 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
371 ASSERT(renderbuffer);
372 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
373 return renderbufferD3D->getRenderTargetSerial();
374 }
375 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
376 {
377 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
378 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
379 ASSERT(defaultAttachmentD3D);
380 return defaultAttachmentD3D->getRenderTarget()->getSerial();
381 }
382 else
383 {
384 UNREACHABLE();
385 return 0;
386 }
387}
388
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500389}