1 //
2 // Copyright 2017 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 // ClearMultiviewGL:
7 // A helper for clearing multiview side-by-side and layered framebuffers.
8 //
9
10 #include "libANGLE/renderer/gl/ClearMultiviewGL.h"
11 #include "libANGLE/renderer/gl/FunctionsGL.h"
12 #include "libANGLE/renderer/gl/StateManagerGL.h"
13 #include "libANGLE/renderer/gl/TextureGL.h"
14
15 #include "libANGLE/Framebuffer.h"
16
17 namespace rx
18 {
19
ClearMultiviewGL(const FunctionsGL * functions,StateManagerGL * stateManager)20 ClearMultiviewGL::ClearMultiviewGL(const FunctionsGL *functions, StateManagerGL *stateManager)
21 : mFunctions(functions), mStateManager(stateManager), mFramebuffer(0u)
22 {}
23
~ClearMultiviewGL()24 ClearMultiviewGL::~ClearMultiviewGL()
25 {
26 if (mFramebuffer != 0u)
27 {
28 mFunctions->deleteFramebuffers(1, &mFramebuffer);
29 }
30 }
31
clearMultiviewFBO(const gl::FramebufferState & state,const gl::Rectangle & scissorBase,ClearCommandType clearCommandType,GLbitfield mask,GLenum buffer,GLint drawbuffer,const uint8_t * values,GLfloat depth,GLint stencil)32 void ClearMultiviewGL::clearMultiviewFBO(const gl::FramebufferState &state,
33 const gl::Rectangle &scissorBase,
34 ClearCommandType clearCommandType,
35 GLbitfield mask,
36 GLenum buffer,
37 GLint drawbuffer,
38 const uint8_t *values,
39 GLfloat depth,
40 GLint stencil)
41 {
42 const gl::FramebufferAttachment *firstAttachment = state.getFirstNonNullAttachment();
43 if (firstAttachment->isMultiview())
44 {
45 clearLayeredFBO(state, clearCommandType, mask, buffer, drawbuffer, values, depth, stencil);
46 }
47 }
48
clearLayeredFBO(const gl::FramebufferState & state,ClearCommandType clearCommandType,GLbitfield mask,GLenum buffer,GLint drawbuffer,const uint8_t * values,GLfloat depth,GLint stencil)49 void ClearMultiviewGL::clearLayeredFBO(const gl::FramebufferState &state,
50 ClearCommandType clearCommandType,
51 GLbitfield mask,
52 GLenum buffer,
53 GLint drawbuffer,
54 const uint8_t *values,
55 GLfloat depth,
56 GLint stencil)
57 {
58 initializeResources();
59
60 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
61
62 const gl::FramebufferAttachment *firstAttachment = state.getFirstNonNullAttachment();
63 ASSERT(firstAttachment->isMultiview());
64
65 const auto &drawBuffers = state.getDrawBufferStates();
66 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()), drawBuffers.data());
67
68 // Attach the new attachments and clear.
69 int numViews = firstAttachment->getNumViews();
70 int baseViewIndex = firstAttachment->getBaseViewIndex();
71 for (int i = 0; i < numViews; ++i)
72 {
73 attachTextures(state, baseViewIndex + i);
74 genericClear(clearCommandType, mask, buffer, drawbuffer, values, depth, stencil);
75 }
76
77 detachTextures(state);
78 }
79
genericClear(ClearCommandType clearCommandType,GLbitfield mask,GLenum buffer,GLint drawbuffer,const uint8_t * values,GLfloat depth,GLint stencil)80 void ClearMultiviewGL::genericClear(ClearCommandType clearCommandType,
81 GLbitfield mask,
82 GLenum buffer,
83 GLint drawbuffer,
84 const uint8_t *values,
85 GLfloat depth,
86 GLint stencil)
87 {
88 switch (clearCommandType)
89 {
90 case ClearCommandType::Clear:
91 mFunctions->clear(mask);
92 break;
93 case ClearCommandType::ClearBufferfv:
94 mFunctions->clearBufferfv(buffer, drawbuffer,
95 reinterpret_cast<const GLfloat *>(values));
96 break;
97 case ClearCommandType::ClearBufferuiv:
98 mFunctions->clearBufferuiv(buffer, drawbuffer,
99 reinterpret_cast<const GLuint *>(values));
100 break;
101 case ClearCommandType::ClearBufferiv:
102 mFunctions->clearBufferiv(buffer, drawbuffer, reinterpret_cast<const GLint *>(values));
103 break;
104 case ClearCommandType::ClearBufferfi:
105 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
106 break;
107 default:
108 UNREACHABLE();
109 }
110 }
111
attachTextures(const gl::FramebufferState & state,int layer)112 void ClearMultiviewGL::attachTextures(const gl::FramebufferState &state, int layer)
113 {
114 for (auto drawBufferId : state.getEnabledDrawBuffers())
115 {
116 const gl::FramebufferAttachment *attachment = state.getColorAttachment(drawBufferId);
117 if (attachment == nullptr)
118 {
119 continue;
120 }
121
122 const auto &imageIndex = attachment->getTextureImageIndex();
123 ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
124
125 GLenum colorAttachment =
126 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + static_cast<int>(drawBufferId));
127 const TextureGL *textureGL = GetImplAs<TextureGL>(attachment->getTexture());
128 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment,
129 textureGL->getTextureID(), imageIndex.getLevelIndex(),
130 layer);
131 }
132
133 const gl::FramebufferAttachment *depthStencilAttachment = state.getDepthStencilAttachment();
134 const gl::FramebufferAttachment *depthAttachment = state.getDepthAttachment();
135 const gl::FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
136 if (depthStencilAttachment != nullptr)
137 {
138 const auto &imageIndex = depthStencilAttachment->getTextureImageIndex();
139 ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
140
141 const TextureGL *textureGL = GetImplAs<TextureGL>(depthStencilAttachment->getTexture());
142 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
143 textureGL->getTextureID(), imageIndex.getLevelIndex(),
144 layer);
145 }
146 else if (depthAttachment != nullptr)
147 {
148 const auto &imageIndex = depthAttachment->getTextureImageIndex();
149 ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
150
151 const TextureGL *textureGL = GetImplAs<TextureGL>(depthAttachment->getTexture());
152 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
153 textureGL->getTextureID(), imageIndex.getLevelIndex(),
154 layer);
155 }
156 else if (stencilAttachment != nullptr)
157 {
158 const auto &imageIndex = stencilAttachment->getTextureImageIndex();
159 ASSERT(imageIndex.getType() == gl::TextureType::_2DArray);
160
161 const TextureGL *textureGL = GetImplAs<TextureGL>(stencilAttachment->getTexture());
162 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
163 textureGL->getTextureID(), imageIndex.getLevelIndex(),
164 layer);
165 }
166 }
167
detachTextures(const gl::FramebufferState & state)168 void ClearMultiviewGL::detachTextures(const gl::FramebufferState &state)
169 {
170 for (auto drawBufferId : state.getEnabledDrawBuffers())
171 {
172 const gl::FramebufferAttachment *attachment = state.getColorAttachment(drawBufferId);
173 if (attachment == nullptr)
174 {
175 continue;
176 }
177
178 GLenum colorAttachment =
179 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + static_cast<int>(drawBufferId));
180 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment, 0, 0, 0);
181 }
182
183 const gl::FramebufferAttachment *depthStencilAttachment = state.getDepthStencilAttachment();
184 const gl::FramebufferAttachment *depthAttachment = state.getDepthAttachment();
185 const gl::FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
186 if (depthStencilAttachment != nullptr)
187 {
188 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0,
189 0);
190 }
191 else if (depthAttachment != nullptr)
192 {
193 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0, 0);
194 }
195 else if (stencilAttachment != nullptr)
196 {
197 mFunctions->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, 0, 0, 0);
198 }
199 }
200
initializeResources()201 void ClearMultiviewGL::initializeResources()
202 {
203 if (mFramebuffer == 0u)
204 {
205 mFunctions->genFramebuffers(1, &mFramebuffer);
206 }
207 ASSERT(mFramebuffer != 0u);
208 }
209
210 } // namespace rx
211