blob: 9dea27e4b860e4641e928c2580d0b7cf9b18c944 [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 Langb5d8f232014-12-04 15:43:01 -050015#include "libANGLE/FramebufferAttachment.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050016
17namespace rx
18{
19
20DefaultAttachmentD3D::DefaultAttachmentD3D(RenderTarget *renderTarget)
21 : mRenderTarget(renderTarget)
22{
23 ASSERT(mRenderTarget);
24}
25
26DefaultAttachmentD3D::~DefaultAttachmentD3D()
27{
28 SafeDelete(mRenderTarget);
29}
30
31DefaultAttachmentD3D *DefaultAttachmentD3D::makeDefaultAttachmentD3D(DefaultAttachmentImpl* impl)
32{
33 ASSERT(HAS_DYNAMIC_TYPE(DefaultAttachmentD3D*, impl));
34 return static_cast<DefaultAttachmentD3D*>(impl);
35}
36
37GLsizei DefaultAttachmentD3D::getWidth() const
38{
39 return mRenderTarget->getWidth();
40}
41
42GLsizei DefaultAttachmentD3D::getHeight() const
43{
44 return mRenderTarget->getHeight();
45}
46
47GLenum DefaultAttachmentD3D::getInternalFormat() const
48{
49 return mRenderTarget->getInternalFormat();
50}
51
52GLenum DefaultAttachmentD3D::getActualFormat() const
53{
54 return mRenderTarget->getActualFormat();
55}
56
57GLsizei DefaultAttachmentD3D::getSamples() const
58{
59 return mRenderTarget->getSamples();
60}
61
62RenderTarget *DefaultAttachmentD3D::getRenderTarget() const
63{
64 return mRenderTarget;
65}
66
Geoff Langda88add2014-12-01 10:22:01 -050067
68FramebufferD3D::FramebufferD3D(RendererD3D *renderer)
Geoff Lang748f74e2014-12-01 11:25:34 -050069 : mRenderer(renderer),
Geoff Langb04dc822014-12-01 12:02:02 -050070 mColorBuffers(renderer->getRendererCaps().maxColorAttachments),
71 mDepthbuffer(nullptr),
72 mStencilbuffer(nullptr),
Geoff Langbce529e2014-12-01 12:48:41 -050073 mDrawBuffers(renderer->getRendererCaps().maxDrawBuffers),
74 mReadBuffer(GL_COLOR_ATTACHMENT0)
Geoff Langda88add2014-12-01 10:22:01 -050075{
76 ASSERT(mRenderer != nullptr);
Geoff Lang748f74e2014-12-01 11:25:34 -050077
78 std::fill(mColorBuffers.begin(), mColorBuffers.end(), nullptr);
Geoff Langb04dc822014-12-01 12:02:02 -050079
80 ASSERT(mDrawBuffers.size() > 0);
81 mDrawBuffers[0] = GL_COLOR_ATTACHMENT0;
82 std::fill(mDrawBuffers.begin() + 1, mDrawBuffers.end(), GL_NONE);
Geoff Langda88add2014-12-01 10:22:01 -050083}
84
85FramebufferD3D::~FramebufferD3D()
86{
87}
88
Geoff Lang9dd95802014-12-01 11:12:59 -050089void FramebufferD3D::setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment)
90{
Geoff Lang748f74e2014-12-01 11:25:34 -050091 ASSERT(index < mColorBuffers.size());
92 mColorBuffers[index] = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050093}
94
95void FramebufferD3D::setDepthttachment(const gl::FramebufferAttachment *attachment)
96{
Geoff Langb04dc822014-12-01 12:02:02 -050097 mDepthbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050098}
99
100void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *attachment)
101{
Geoff Langb04dc822014-12-01 12:02:02 -0500102 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500103}
104
105void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *attachment)
106{
Geoff Langb04dc822014-12-01 12:02:02 -0500107 mDepthbuffer = attachment;
108 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500109}
110
111void FramebufferD3D::setDrawBuffers(size_t count, const GLenum *buffers)
112{
Geoff Langb04dc822014-12-01 12:02:02 -0500113 std::copy_n(buffers, count, mDrawBuffers.begin());
114 std::fill(mDrawBuffers.begin() + count, mDrawBuffers.end(), GL_NONE);
Geoff Lang9dd95802014-12-01 11:12:59 -0500115}
116
117void FramebufferD3D::setReadBuffer(GLenum buffer)
118{
Geoff Langbce529e2014-12-01 12:48:41 -0500119 mReadBuffer = buffer;
Geoff Lang9dd95802014-12-01 11:12:59 -0500120}
121
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500122gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
123{
124 // No-op in D3D
125 return gl::Error(GL_NO_ERROR);
126}
127
128gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
129{
130 // No-op in D3D
131 return gl::Error(GL_NO_ERROR);
132}
133
Geoff Langb04dc822014-12-01 12:02:02 -0500134gl::Error FramebufferD3D::clear(const gl::State &state, GLbitfield mask)
135{
136 gl::ClearParameters clearParams = state.getClearParameters(mask);
137 return clear(state, clearParams);
138}
139
140gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
141{
142 // glClearBufferfv can be called to clear the color buffer or depth buffer
143 gl::ClearParameters clearParams = state.getClearParameters(0);
144
145 if (buffer == GL_COLOR)
146 {
147 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
148 {
149 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
150 }
151 clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
152 clearParams.colorClearType = GL_FLOAT;
153 }
154
155 if (buffer == GL_DEPTH)
156 {
157 clearParams.clearDepth = true;
158 clearParams.depthClearValue = values[0];
159 }
160
161 return clear(state, clearParams);
162}
163
164gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
165{
166 // glClearBufferuiv can only be called to clear a color buffer
167 gl::ClearParameters clearParams = state.getClearParameters(0);
168 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
169 {
170 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
171 }
172 clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
173 clearParams.colorClearType = GL_UNSIGNED_INT;
174
175 return clear(state, clearParams);
176}
177
178gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
179{
180 // glClearBufferiv can be called to clear the color buffer or stencil buffer
181 gl::ClearParameters clearParams = state.getClearParameters(0);
182
183 if (buffer == GL_COLOR)
184 {
185 for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
186 {
187 clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
188 }
189 clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
190 clearParams.colorClearType = GL_INT;
191 }
192
193 if (buffer == GL_STENCIL)
194 {
195 clearParams.clearStencil = true;
196 clearParams.stencilClearValue = values[1];
197 }
198
199 return clear(state, clearParams);
200}
201
202gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
203{
204 // glClearBufferfi can only be called to clear a depth stencil buffer
205 gl::ClearParameters clearParams = state.getClearParameters(0);
206 clearParams.clearDepth = true;
207 clearParams.depthClearValue = depth;
208 clearParams.clearStencil = true;
209 clearParams.stencilClearValue = stencil;
210
211 return clear(state, clearParams);
212}
213
Geoff Langbce529e2014-12-01 12:48:41 -0500214GLenum FramebufferD3D::getImplementationColorReadFormat() const
215{
216 // Will require more logic if glReadBuffers is supported
217 ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
218
219 if (mColorBuffers[0] == nullptr)
220 {
221 return GL_NONE;
222 }
223
224 GLenum actualFormat = mColorBuffers[0]->getActualFormat();
225 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualFormat);
226
227 return actualFormatInfo.format;
228}
229
230GLenum FramebufferD3D::getImplementationColorReadType() const
231{
232 // Will require more logic if glReadBuffers is supported
233 ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
234
235 if (mColorBuffers[0] == nullptr)
236 {
237 return GL_NONE;
238 }
239
240 GLenum actualFormat = mColorBuffers[0]->getActualFormat();
241 const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualFormat);
242
243 return actualFormatInfo.type;
244}
245
246gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
247{
248 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
249 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
250 GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment());
251
252 return readPixels(area, format, type, outputPitch, state.getPackState(), reinterpret_cast<uint8_t*>(pixels));
253}
254
Geoff Lang748f74e2014-12-01 11:25:34 -0500255GLenum FramebufferD3D::checkStatus() const
256{
257 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
258 for (size_t colorAttachment = 0; colorAttachment < mColorBuffers.size(); colorAttachment++)
259 {
260 const gl::FramebufferAttachment *attachment = mColorBuffers[colorAttachment];
261 if (attachment != nullptr)
262 {
263 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
264 {
265 const gl::FramebufferAttachment *prevAttachment = mColorBuffers[prevColorAttachment];
266 if (prevAttachment != nullptr &&
267 (attachment->id() == prevAttachment->id() &&
268 attachment->type() == prevAttachment->type()))
269 {
270 return GL_FRAMEBUFFER_UNSUPPORTED;
271 }
272 }
273 }
274 }
275
276 return GL_FRAMEBUFFER_COMPLETE;
277}
278
Geoff Langb5d8f232014-12-04 15:43:01 -0500279gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget **outRT)
280{
281 if (attachment->type() == GL_TEXTURE)
282 {
283 gl::Texture *texture = attachment->getTexture();
284 ASSERT(texture);
285 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
286 const gl::ImageIndex *index = attachment->getTextureImageIndex();
287 ASSERT(index);
288 return textureD3D->getRenderTarget(*index, outRT);
289 }
290 else if (attachment->type() == GL_RENDERBUFFER)
291 {
292 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
293 ASSERT(renderbuffer);
294 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
295 *outRT = renderbufferD3D->getRenderTarget();
296 return gl::Error(GL_NO_ERROR);
297 }
298 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
299 {
300 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
301 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
302 ASSERT(defaultAttachmentD3D);
303
304 *outRT = defaultAttachmentD3D->getRenderTarget();
305 return gl::Error(GL_NO_ERROR);
306 }
307 else
308 {
309 UNREACHABLE();
310 return gl::Error(GL_INVALID_OPERATION);
311 }
312}
313
314// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
315unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
316{
317 if (attachment->type() == GL_TEXTURE)
318 {
319 gl::Texture *texture = attachment->getTexture();
320 ASSERT(texture);
321 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
322 const gl::ImageIndex *index = attachment->getTextureImageIndex();
323 ASSERT(index);
324 return textureD3D->getRenderTargetSerial(*index);
325 }
326 else if (attachment->type() == GL_RENDERBUFFER)
327 {
328 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
329 ASSERT(renderbuffer);
330 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
331 return renderbufferD3D->getRenderTargetSerial();
332 }
333 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
334 {
335 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
336 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
337 ASSERT(defaultAttachmentD3D);
338 return defaultAttachmentD3D->getRenderTarget()->getSerial();
339 }
340 else
341 {
342 UNREACHABLE();
343 return 0;
344 }
345}
346
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500347}