blob: 0dd20e5f7df917907d30aa082af1f6ebd2624cd7 [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 Langb5d8f232014-12-04 15:43:01 -050014#include "libANGLE/FramebufferAttachment.h"
Geoff Lang6a1e6b92014-11-06 10:42:45 -050015
16namespace rx
17{
18
19DefaultAttachmentD3D::DefaultAttachmentD3D(RenderTarget *renderTarget)
20 : mRenderTarget(renderTarget)
21{
22 ASSERT(mRenderTarget);
23}
24
25DefaultAttachmentD3D::~DefaultAttachmentD3D()
26{
27 SafeDelete(mRenderTarget);
28}
29
30DefaultAttachmentD3D *DefaultAttachmentD3D::makeDefaultAttachmentD3D(DefaultAttachmentImpl* impl)
31{
32 ASSERT(HAS_DYNAMIC_TYPE(DefaultAttachmentD3D*, impl));
33 return static_cast<DefaultAttachmentD3D*>(impl);
34}
35
36GLsizei DefaultAttachmentD3D::getWidth() const
37{
38 return mRenderTarget->getWidth();
39}
40
41GLsizei DefaultAttachmentD3D::getHeight() const
42{
43 return mRenderTarget->getHeight();
44}
45
46GLenum DefaultAttachmentD3D::getInternalFormat() const
47{
48 return mRenderTarget->getInternalFormat();
49}
50
51GLenum DefaultAttachmentD3D::getActualFormat() const
52{
53 return mRenderTarget->getActualFormat();
54}
55
56GLsizei DefaultAttachmentD3D::getSamples() const
57{
58 return mRenderTarget->getSamples();
59}
60
61RenderTarget *DefaultAttachmentD3D::getRenderTarget() const
62{
63 return mRenderTarget;
64}
65
Geoff Langda88add2014-12-01 10:22:01 -050066
67FramebufferD3D::FramebufferD3D(RendererD3D *renderer)
Geoff Lang748f74e2014-12-01 11:25:34 -050068 : mRenderer(renderer),
Geoff Langb04dc822014-12-01 12:02:02 -050069 mColorBuffers(renderer->getRendererCaps().maxColorAttachments),
70 mDepthbuffer(nullptr),
71 mStencilbuffer(nullptr),
72 mDrawBuffers(renderer->getRendererCaps().maxDrawBuffers)
Geoff Langda88add2014-12-01 10:22:01 -050073{
74 ASSERT(mRenderer != nullptr);
Geoff Lang748f74e2014-12-01 11:25:34 -050075
76 std::fill(mColorBuffers.begin(), mColorBuffers.end(), nullptr);
Geoff Langb04dc822014-12-01 12:02:02 -050077
78 ASSERT(mDrawBuffers.size() > 0);
79 mDrawBuffers[0] = GL_COLOR_ATTACHMENT0;
80 std::fill(mDrawBuffers.begin() + 1, mDrawBuffers.end(), GL_NONE);
Geoff Langda88add2014-12-01 10:22:01 -050081}
82
83FramebufferD3D::~FramebufferD3D()
84{
85}
86
Geoff Lang9dd95802014-12-01 11:12:59 -050087void FramebufferD3D::setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment)
88{
Geoff Lang748f74e2014-12-01 11:25:34 -050089 ASSERT(index < mColorBuffers.size());
90 mColorBuffers[index] = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050091}
92
93void FramebufferD3D::setDepthttachment(const gl::FramebufferAttachment *attachment)
94{
Geoff Langb04dc822014-12-01 12:02:02 -050095 mDepthbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -050096}
97
98void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *attachment)
99{
Geoff Langb04dc822014-12-01 12:02:02 -0500100 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500101}
102
103void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *attachment)
104{
Geoff Langb04dc822014-12-01 12:02:02 -0500105 mDepthbuffer = attachment;
106 mStencilbuffer = attachment;
Geoff Lang9dd95802014-12-01 11:12:59 -0500107}
108
109void FramebufferD3D::setDrawBuffers(size_t count, const GLenum *buffers)
110{
Geoff Langb04dc822014-12-01 12:02:02 -0500111 std::copy_n(buffers, count, mDrawBuffers.begin());
112 std::fill(mDrawBuffers.begin() + count, mDrawBuffers.end(), GL_NONE);
Geoff Lang9dd95802014-12-01 11:12:59 -0500113}
114
115void FramebufferD3D::setReadBuffer(GLenum buffer)
116{
117}
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
Geoff Lang748f74e2014-12-01 11:25:34 -0500211GLenum FramebufferD3D::checkStatus() const
212{
213 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
214 for (size_t colorAttachment = 0; colorAttachment < mColorBuffers.size(); colorAttachment++)
215 {
216 const gl::FramebufferAttachment *attachment = mColorBuffers[colorAttachment];
217 if (attachment != nullptr)
218 {
219 for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
220 {
221 const gl::FramebufferAttachment *prevAttachment = mColorBuffers[prevColorAttachment];
222 if (prevAttachment != nullptr &&
223 (attachment->id() == prevAttachment->id() &&
224 attachment->type() == prevAttachment->type()))
225 {
226 return GL_FRAMEBUFFER_UNSUPPORTED;
227 }
228 }
229 }
230 }
231
232 return GL_FRAMEBUFFER_COMPLETE;
233}
234
Geoff Langb5d8f232014-12-04 15:43:01 -0500235gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget **outRT)
236{
237 if (attachment->type() == GL_TEXTURE)
238 {
239 gl::Texture *texture = attachment->getTexture();
240 ASSERT(texture);
241 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
242 const gl::ImageIndex *index = attachment->getTextureImageIndex();
243 ASSERT(index);
244 return textureD3D->getRenderTarget(*index, outRT);
245 }
246 else if (attachment->type() == GL_RENDERBUFFER)
247 {
248 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
249 ASSERT(renderbuffer);
250 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
251 *outRT = renderbufferD3D->getRenderTarget();
252 return gl::Error(GL_NO_ERROR);
253 }
254 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
255 {
256 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
257 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
258 ASSERT(defaultAttachmentD3D);
259
260 *outRT = defaultAttachmentD3D->getRenderTarget();
261 return gl::Error(GL_NO_ERROR);
262 }
263 else
264 {
265 UNREACHABLE();
266 return gl::Error(GL_INVALID_OPERATION);
267 }
268}
269
270// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
271unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
272{
273 if (attachment->type() == GL_TEXTURE)
274 {
275 gl::Texture *texture = attachment->getTexture();
276 ASSERT(texture);
277 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
278 const gl::ImageIndex *index = attachment->getTextureImageIndex();
279 ASSERT(index);
280 return textureD3D->getRenderTargetSerial(*index);
281 }
282 else if (attachment->type() == GL_RENDERBUFFER)
283 {
284 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
285 ASSERT(renderbuffer);
286 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
287 return renderbufferD3D->getRenderTargetSerial();
288 }
289 else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
290 {
291 const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
292 DefaultAttachmentD3D *defaultAttachmentD3D = DefaultAttachmentD3D::makeDefaultAttachmentD3D(defaultAttachment->getImplementation());
293 ASSERT(defaultAttachmentD3D);
294 return defaultAttachmentD3D->getRenderTarget()->getSerial();
295 }
296 else
297 {
298 UNREACHABLE();
299 return 0;
300 }
301}
302
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500303}