Renderbuffer.cpp (12985B)
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 29 InitState DetermineInitState(const Context *context) 30 { 31 return (context && context->isRobustResourceInitEnabled()) ? InitState::MayNeedInit 32 : InitState::Initialized; 33 } 34 } // namespace 35 36 // RenderbufferState implementation. 37 RenderbufferState::RenderbufferState() 38 : mWidth(0), 39 mHeight(0), 40 mFormat(GL_RGBA4), 41 mSamples(0), 42 mMultisamplingMode(MultisamplingMode::Regular), 43 mHasProtectedContent(false), 44 mInitState(InitState::Initialized) 45 {} 46 47 RenderbufferState::~RenderbufferState() {} 48 49 GLsizei RenderbufferState::getWidth() const 50 { 51 return mWidth; 52 } 53 54 GLsizei RenderbufferState::getHeight() const 55 { 56 return mHeight; 57 } 58 59 const Format &RenderbufferState::getFormat() const 60 { 61 return mFormat; 62 } 63 64 GLsizei RenderbufferState::getSamples() const 65 { 66 return mSamples; 67 } 68 69 MultisamplingMode RenderbufferState::getMultisamplingMode() const 70 { 71 return mMultisamplingMode; 72 } 73 74 InitState RenderbufferState::getInitState() const 75 { 76 return mInitState; 77 } 78 79 void RenderbufferState::update(GLsizei width, 80 GLsizei height, 81 const Format &format, 82 GLsizei samples, 83 MultisamplingMode multisamplingMode, 84 InitState initState) 85 { 86 mWidth = width; 87 mHeight = height; 88 mFormat = format; 89 mSamples = samples; 90 mMultisamplingMode = multisamplingMode; 91 mInitState = initState; 92 mHasProtectedContent = false; 93 } 94 95 void RenderbufferState::setProtectedContent(bool hasProtectedContent) 96 { 97 mHasProtectedContent = hasProtectedContent; 98 } 99 100 // Renderbuffer implementation. 101 Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id) 102 : RefCountObject(implFactory->generateSerial(), id), 103 mState(), 104 mImplementation(implFactory->createRenderbuffer(mState)), 105 mLabel(), 106 mImplObserverBinding(this, kRenderbufferImplSubjectIndex) 107 { 108 mImplObserverBinding.bind(mImplementation.get()); 109 } 110 111 void Renderbuffer::onDestroy(const Context *context) 112 { 113 egl::RefCountObjectReleaser<egl::Image> releaseImage; 114 (void)orphanImages(context, &releaseImage); 115 116 if (mImplementation) 117 { 118 mImplementation->onDestroy(context); 119 } 120 } 121 122 Renderbuffer::~Renderbuffer() {} 123 124 angle::Result Renderbuffer::setLabel(const Context *context, const std::string &label) 125 { 126 mLabel = label; 127 128 if (mImplementation) 129 { 130 return mImplementation->onLabelUpdate(context); 131 } 132 return angle::Result::Continue; 133 } 134 135 const std::string &Renderbuffer::getLabel() const 136 { 137 return mLabel; 138 } 139 140 angle::Result Renderbuffer::setStorage(const Context *context, 141 GLenum internalformat, 142 GLsizei width, 143 GLsizei height) 144 { 145 146 egl::RefCountObjectReleaser<egl::Image> releaseImage; 147 ANGLE_TRY(orphanImages(context, &releaseImage)); 148 149 ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height)); 150 151 mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular, 152 DetermineInitState(context)); 153 onStateChange(angle::SubjectMessage::SubjectChanged); 154 155 return angle::Result::Continue; 156 } 157 158 angle::Result Renderbuffer::setStorageMultisample(const Context *context, 159 GLsizei samplesIn, 160 GLenum internalformat, 161 GLsizei width, 162 GLsizei height, 163 MultisamplingMode mode) 164 { 165 egl::RefCountObjectReleaser<egl::Image> releaseImage; 166 ANGLE_TRY(orphanImages(context, &releaseImage)); 167 168 // Potentially adjust "samplesIn" to a supported value 169 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); 170 GLsizei samples = formatCaps.getNearestSamples(samplesIn); 171 172 ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width, 173 height, mode)); 174 175 mState.update(width, height, Format(internalformat), samples, mode, 176 DetermineInitState(context)); 177 onStateChange(angle::SubjectMessage::SubjectChanged); 178 179 return angle::Result::Continue; 180 } 181 182 angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image) 183 { 184 egl::RefCountObjectReleaser<egl::Image> releaseImage; 185 ANGLE_TRY(orphanImages(context, &releaseImage)); 186 187 ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image)); 188 189 setTargetImage(context, image); 190 191 mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()), 192 Format(image->getFormat()), 0, MultisamplingMode::Regular, 193 image->sourceInitState()); 194 mState.setProtectedContent(image->hasProtectedContent()); 195 196 onStateChange(angle::SubjectMessage::SubjectChanged); 197 198 return angle::Result::Continue; 199 } 200 201 angle::Result Renderbuffer::copyRenderbufferSubData(Context *context, 202 const gl::Renderbuffer *srcBuffer, 203 GLint srcLevel, 204 GLint srcX, 205 GLint srcY, 206 GLint srcZ, 207 GLint dstLevel, 208 GLint dstX, 209 GLint dstY, 210 GLint dstZ, 211 GLsizei srcWidth, 212 GLsizei srcHeight, 213 GLsizei srcDepth) 214 { 215 ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY, 216 srcZ, dstLevel, dstX, dstY, dstZ, srcWidth, 217 srcHeight, srcDepth)); 218 219 return angle::Result::Continue; 220 } 221 222 angle::Result Renderbuffer::copyTextureSubData(Context *context, 223 const gl::Texture *srcTexture, 224 GLint srcLevel, 225 GLint srcX, 226 GLint srcY, 227 GLint srcZ, 228 GLint dstLevel, 229 GLint dstX, 230 GLint dstY, 231 GLint dstZ, 232 GLsizei srcWidth, 233 GLsizei srcHeight, 234 GLsizei srcDepth) 235 { 236 ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ, 237 dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, 238 srcDepth)); 239 240 return angle::Result::Continue; 241 } 242 243 rx::RenderbufferImpl *Renderbuffer::getImplementation() const 244 { 245 ASSERT(mImplementation); 246 return mImplementation.get(); 247 } 248 249 GLsizei Renderbuffer::getWidth() const 250 { 251 return mState.mWidth; 252 } 253 254 GLsizei Renderbuffer::getHeight() const 255 { 256 return mState.mHeight; 257 } 258 259 const Format &Renderbuffer::getFormat() const 260 { 261 return mState.mFormat; 262 } 263 264 GLsizei Renderbuffer::getSamples() const 265 { 266 return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0; 267 } 268 269 MultisamplingMode Renderbuffer::getMultisamplingMode() const 270 { 271 return mState.mMultisamplingMode; 272 } 273 274 GLuint Renderbuffer::getRedSize() const 275 { 276 return mState.mFormat.info->redBits; 277 } 278 279 GLuint Renderbuffer::getGreenSize() const 280 { 281 return mState.mFormat.info->greenBits; 282 } 283 284 GLuint Renderbuffer::getBlueSize() const 285 { 286 return mState.mFormat.info->blueBits; 287 } 288 289 GLuint Renderbuffer::getAlphaSize() const 290 { 291 return mState.mFormat.info->alphaBits; 292 } 293 294 GLuint Renderbuffer::getDepthSize() const 295 { 296 return mState.mFormat.info->depthBits; 297 } 298 299 GLuint Renderbuffer::getStencilSize() const 300 { 301 return mState.mFormat.info->stencilBits; 302 } 303 304 const RenderbufferState &Renderbuffer::getState() const 305 { 306 return mState; 307 } 308 309 GLint Renderbuffer::getMemorySize() const 310 { 311 GLint implSize = mImplementation->getMemorySize(); 312 if (implSize > 0) 313 { 314 return implSize; 315 } 316 317 // Assume allocated size is around width * height * samples * pixelBytes 318 angle::CheckedNumeric<GLint> size = 1; 319 size *= mState.mFormat.info->pixelBytes; 320 size *= mState.mWidth; 321 size *= mState.mHeight; 322 size *= std::max(mState.mSamples, 1); 323 return size.ValueOrDefault(std::numeric_limits<GLint>::max()); 324 } 325 326 void Renderbuffer::onAttach(const Context *context, rx::Serial framebufferSerial) 327 { 328 addRef(); 329 } 330 331 void Renderbuffer::onDetach(const Context *context, rx::Serial framebufferSerial) 332 { 333 release(context); 334 } 335 336 GLuint Renderbuffer::getId() const 337 { 338 return id().value; 339 } 340 341 Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const 342 { 343 return Extents(mState.mWidth, mState.mHeight, 1); 344 } 345 346 Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/, 347 const ImageIndex & /*imageIndex*/) const 348 { 349 return getFormat(); 350 } 351 GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const 352 { 353 return getSamples(); 354 } 355 356 bool Renderbuffer::isRenderable(const Context *context, 357 GLenum binding, 358 const ImageIndex &imageIndex) const 359 { 360 if (isEGLImageTarget()) 361 { 362 return ImageSibling::isRenderable(context, binding, imageIndex); 363 } 364 return getFormat().info->renderbufferSupport(context->getClientVersion(), 365 context->getExtensions()); 366 } 367 368 InitState Renderbuffer::initState(GLenum /*binding*/, const gl::ImageIndex & /*imageIndex*/) const 369 { 370 if (isEGLImageTarget()) 371 { 372 return sourceEGLImageInitState(); 373 } 374 375 return mState.mInitState; 376 } 377 378 void Renderbuffer::setInitState(GLenum /*binding*/, 379 const gl::ImageIndex & /*imageIndex*/, 380 InitState initState) 381 { 382 if (isEGLImageTarget()) 383 { 384 setSourceEGLImageInitState(initState); 385 } 386 else 387 { 388 mState.mInitState = initState; 389 } 390 } 391 392 rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const 393 { 394 return mImplementation.get(); 395 } 396 397 GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const 398 { 399 return mImplementation->getColorReadFormat(context); 400 } 401 402 GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const 403 { 404 return mImplementation->getColorReadType(context); 405 } 406 407 angle::Result Renderbuffer::getRenderbufferImage(const Context *context, 408 const PixelPackState &packState, 409 Buffer *packBuffer, 410 GLenum format, 411 GLenum type, 412 void *pixels) const 413 { 414 return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type, 415 pixels); 416 } 417 418 void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) 419 { 420 ASSERT(message == angle::SubjectMessage::SubjectChanged); 421 onStateChange(angle::SubjectMessage::ContentsChanged); 422 } 423 } // namespace gl