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