1 //
2 // Copyright 2002 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
7 // Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class,
8 // GL renderbuffer objects and related functionality.
9 // [OpenGL ES 2.0.24] section 4.4.3 page 108.
10
11 #include "libANGLE/Renderbuffer.h"
12
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/FramebufferAttachment.h"
16 #include "libANGLE/Image.h"
17 #include "libANGLE/Renderbuffer.h"
18 #include "libANGLE/Texture.h"
19 #include "libANGLE/formatutils.h"
20 #include "libANGLE/renderer/GLImplFactory.h"
21 #include "libANGLE/renderer/d3d/RenderTargetD3D.h"
22
23 namespace gl
24 {
25 namespace
26 {
27 angle::SubjectIndex kRenderbufferImplSubjectIndex = 0;
28 } // namespace
29
30 // RenderbufferState implementation.
RenderbufferState()31 RenderbufferState::RenderbufferState()
32 : mWidth(0),
33 mHeight(0),
34 mFormat(GL_RGBA4),
35 mSamples(0),
36 mMultisamplingMode(MultisamplingMode::Regular),
37 mInitState(InitState::Initialized)
38 {}
39
~RenderbufferState()40 RenderbufferState::~RenderbufferState() {}
41
getWidth() const42 GLsizei RenderbufferState::getWidth() const
43 {
44 return mWidth;
45 }
46
getHeight() const47 GLsizei RenderbufferState::getHeight() const
48 {
49 return mHeight;
50 }
51
getFormat() const52 const Format &RenderbufferState::getFormat() const
53 {
54 return mFormat;
55 }
56
getSamples() const57 GLsizei RenderbufferState::getSamples() const
58 {
59 return mSamples;
60 }
61
getMultisamplingMode() const62 MultisamplingMode RenderbufferState::getMultisamplingMode() const
63 {
64 return mMultisamplingMode;
65 }
66
getInitState() const67 InitState RenderbufferState::getInitState() const
68 {
69 return mInitState;
70 }
71
update(GLsizei width,GLsizei height,const Format & format,GLsizei samples,MultisamplingMode multisamplingMode,InitState initState)72 void RenderbufferState::update(GLsizei width,
73 GLsizei height,
74 const Format &format,
75 GLsizei samples,
76 MultisamplingMode multisamplingMode,
77 InitState initState)
78 {
79 mWidth = width;
80 mHeight = height;
81 mFormat = format;
82 mSamples = samples;
83 mMultisamplingMode = multisamplingMode;
84 mInitState = InitState::MayNeedInit;
85 }
86
87 // Renderbuffer implementation.
Renderbuffer(rx::GLImplFactory * implFactory,RenderbufferID id)88 Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
89 : RefCountObject(implFactory->generateSerial(), id),
90 mState(),
91 mImplementation(implFactory->createRenderbuffer(mState)),
92 mLabel(),
93 mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
94 {
95 mImplObserverBinding.bind(mImplementation.get());
96 }
97
onDestroy(const Context * context)98 void Renderbuffer::onDestroy(const Context *context)
99 {
100 (void)(orphanImages(context));
101
102 if (mImplementation)
103 {
104 mImplementation->onDestroy(context);
105 }
106 }
107
~Renderbuffer()108 Renderbuffer::~Renderbuffer() {}
109
setLabel(const Context * context,const std::string & label)110 void Renderbuffer::setLabel(const Context *context, const std::string &label)
111 {
112 mLabel = label;
113 }
114
getLabel() const115 const std::string &Renderbuffer::getLabel() const
116 {
117 return mLabel;
118 }
119
setStorage(const Context * context,GLenum internalformat,GLsizei width,GLsizei height)120 angle::Result Renderbuffer::setStorage(const Context *context,
121 GLenum internalformat,
122 GLsizei width,
123 GLsizei height)
124 {
125 ANGLE_TRY(orphanImages(context));
126 ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));
127
128 mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular,
129 InitState::MayNeedInit);
130 onStateChange(angle::SubjectMessage::SubjectChanged);
131
132 return angle::Result::Continue;
133 }
134
setStorageMultisample(const Context * context,GLsizei samplesIn,GLenum internalformat,GLsizei width,GLsizei height,MultisamplingMode mode)135 angle::Result Renderbuffer::setStorageMultisample(const Context *context,
136 GLsizei samplesIn,
137 GLenum internalformat,
138 GLsizei width,
139 GLsizei height,
140 MultisamplingMode mode)
141 {
142 ANGLE_TRY(orphanImages(context));
143
144 // Potentially adjust "samplesIn" to a supported value
145 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
146 GLsizei samples = formatCaps.getNearestSamples(samplesIn);
147
148 ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width,
149 height, mode));
150
151 mState.update(width, height, Format(internalformat), samples, mode, InitState::MayNeedInit);
152 onStateChange(angle::SubjectMessage::SubjectChanged);
153
154 return angle::Result::Continue;
155 }
156
setStorageEGLImageTarget(const Context * context,egl::Image * image)157 angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
158 {
159 ANGLE_TRY(orphanImages(context));
160 ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));
161
162 setTargetImage(context, image);
163
164 mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
165 Format(image->getFormat()), 0, MultisamplingMode::Regular,
166 image->sourceInitState());
167 onStateChange(angle::SubjectMessage::SubjectChanged);
168
169 return angle::Result::Continue;
170 }
171
copyRenderbufferSubData(Context * context,const gl::Renderbuffer * srcBuffer,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)172 angle::Result Renderbuffer::copyRenderbufferSubData(Context *context,
173 const gl::Renderbuffer *srcBuffer,
174 GLint srcLevel,
175 GLint srcX,
176 GLint srcY,
177 GLint srcZ,
178 GLint dstLevel,
179 GLint dstX,
180 GLint dstY,
181 GLint dstZ,
182 GLsizei srcWidth,
183 GLsizei srcHeight,
184 GLsizei srcDepth)
185 {
186 ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY,
187 srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
188 srcHeight, srcDepth));
189
190 return angle::Result::Continue;
191 }
192
copyTextureSubData(Context * context,const gl::Texture * srcTexture,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)193 angle::Result Renderbuffer::copyTextureSubData(Context *context,
194 const gl::Texture *srcTexture,
195 GLint srcLevel,
196 GLint srcX,
197 GLint srcY,
198 GLint srcZ,
199 GLint dstLevel,
200 GLint dstX,
201 GLint dstY,
202 GLint dstZ,
203 GLsizei srcWidth,
204 GLsizei srcHeight,
205 GLsizei srcDepth)
206 {
207 ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
208 dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
209 srcDepth));
210
211 return angle::Result::Continue;
212 }
213
getImplementation() const214 rx::RenderbufferImpl *Renderbuffer::getImplementation() const
215 {
216 ASSERT(mImplementation);
217 return mImplementation.get();
218 }
219
getWidth() const220 GLsizei Renderbuffer::getWidth() const
221 {
222 return mState.mWidth;
223 }
224
getHeight() const225 GLsizei Renderbuffer::getHeight() const
226 {
227 return mState.mHeight;
228 }
229
getFormat() const230 const Format &Renderbuffer::getFormat() const
231 {
232 return mState.mFormat;
233 }
234
getSamples() const235 GLsizei Renderbuffer::getSamples() const
236 {
237 return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0;
238 }
239
getMultisamplingMode() const240 MultisamplingMode Renderbuffer::getMultisamplingMode() const
241 {
242 return mState.mMultisamplingMode;
243 }
244
getRedSize() const245 GLuint Renderbuffer::getRedSize() const
246 {
247 return mState.mFormat.info->redBits;
248 }
249
getGreenSize() const250 GLuint Renderbuffer::getGreenSize() const
251 {
252 return mState.mFormat.info->greenBits;
253 }
254
getBlueSize() const255 GLuint Renderbuffer::getBlueSize() const
256 {
257 return mState.mFormat.info->blueBits;
258 }
259
getAlphaSize() const260 GLuint Renderbuffer::getAlphaSize() const
261 {
262 return mState.mFormat.info->alphaBits;
263 }
264
getDepthSize() const265 GLuint Renderbuffer::getDepthSize() const
266 {
267 return mState.mFormat.info->depthBits;
268 }
269
getStencilSize() const270 GLuint Renderbuffer::getStencilSize() const
271 {
272 return mState.mFormat.info->stencilBits;
273 }
274
getState() const275 const RenderbufferState &Renderbuffer::getState() const
276 {
277 return mState;
278 }
279
getMemorySize() const280 GLint Renderbuffer::getMemorySize() const
281 {
282 GLint implSize = mImplementation->getMemorySize();
283 if (implSize > 0)
284 {
285 return implSize;
286 }
287
288 // Assume allocated size is around width * height * samples * pixelBytes
289 angle::CheckedNumeric<GLint> size = 1;
290 size *= mState.mFormat.info->pixelBytes;
291 size *= mState.mWidth;
292 size *= mState.mHeight;
293 size *= std::max(mState.mSamples, 1);
294 return size.ValueOrDefault(std::numeric_limits<GLint>::max());
295 }
296
onAttach(const Context * context,rx::Serial framebufferSerial)297 void Renderbuffer::onAttach(const Context *context, rx::Serial framebufferSerial)
298 {
299 addRef();
300 }
301
onDetach(const Context * context,rx::Serial framebufferSerial)302 void Renderbuffer::onDetach(const Context *context, rx::Serial framebufferSerial)
303 {
304 release(context);
305 }
306
getId() const307 GLuint Renderbuffer::getId() const
308 {
309 return id().value;
310 }
311
getAttachmentSize(const gl::ImageIndex &) const312 Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
313 {
314 return Extents(mState.mWidth, mState.mHeight, 1);
315 }
316
getAttachmentFormat(GLenum,const ImageIndex &) const317 Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
318 const ImageIndex & /*imageIndex*/) const
319 {
320 return getFormat();
321 }
getAttachmentSamples(const ImageIndex &) const322 GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
323 {
324 return getSamples();
325 }
326
isRenderable(const Context * context,GLenum binding,const ImageIndex & imageIndex) const327 bool Renderbuffer::isRenderable(const Context *context,
328 GLenum binding,
329 const ImageIndex &imageIndex) const
330 {
331 if (isEGLImageTarget())
332 {
333 return ImageSibling::isRenderable(context, binding, imageIndex);
334 }
335 return getFormat().info->renderbufferSupport(context->getClientVersion(),
336 context->getExtensions());
337 }
338
initState(const gl::ImageIndex &) const339 InitState Renderbuffer::initState(const gl::ImageIndex & /*imageIndex*/) const
340 {
341 if (isEGLImageTarget())
342 {
343 return sourceEGLImageInitState();
344 }
345
346 return mState.mInitState;
347 }
348
setInitState(const gl::ImageIndex &,InitState initState)349 void Renderbuffer::setInitState(const gl::ImageIndex & /*imageIndex*/, InitState initState)
350 {
351 if (isEGLImageTarget())
352 {
353 setSourceEGLImageInitState(initState);
354 }
355 else
356 {
357 mState.mInitState = initState;
358 }
359 }
360
getAttachmentImpl() const361 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
362 {
363 return mImplementation.get();
364 }
365
getImplementationColorReadFormat(const Context * context) const366 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
367 {
368 return mImplementation->getColorReadFormat(context);
369 }
370
getImplementationColorReadType(const Context * context) const371 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
372 {
373 return mImplementation->getColorReadType(context);
374 }
375
getRenderbufferImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,GLenum format,GLenum type,void * pixels) const376 angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
377 const PixelPackState &packState,
378 Buffer *packBuffer,
379 GLenum format,
380 GLenum type,
381 void *pixels) const
382 {
383 return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
384 pixels);
385 }
386
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)387 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
388 {
389 ASSERT(message == angle::SubjectMessage::SubjectChanged);
390 onStateChange(angle::SubjectMessage::ContentsChanged);
391 }
392 } // namespace gl
393