| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "GrGLGpu.h" | 9 #include "GrGLGpu.h" |
| 10 #include "GrGLGLSL.h" | 10 #include "GrGLGLSL.h" |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 return nullptr; | 180 return nullptr; |
| 181 } | 181 } |
| 182 | 182 |
| 183 static bool gPrintStartupSpew; | 183 static bool gPrintStartupSpew; |
| 184 | 184 |
| 185 GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context) | 185 GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context) |
| 186 : GrGpu(context) | 186 : GrGpu(context) |
| 187 , fGLContext(ctx) { | 187 , fGLContext(ctx) { |
| 188 SkASSERT(ctx); | 188 SkASSERT(ctx); |
| 189 fCaps.reset(SkRef(ctx->caps())); | 189 fCaps.reset(SkRef(ctx->caps())); |
| 190 this->generateConfigTable(); | |
| 191 | 190 |
| 192 fHWBoundTextureUniqueIDs.reset(this->glCaps().maxFragmentTextureUnits()); | 191 fHWBoundTextureUniqueIDs.reset(this->glCaps().maxFragmentTextureUnits()); |
| 193 | 192 |
| 194 GrGLClearErr(this->glInterface()); | 193 GrGLClearErr(this->glInterface()); |
| 195 if (gPrintStartupSpew) { | 194 if (gPrintStartupSpew) { |
| 196 const GrGLubyte* vendor; | 195 const GrGLubyte* vendor; |
| 197 const GrGLubyte* renderer; | 196 const GrGLubyte* renderer; |
| 198 const GrGLubyte* version; | 197 const GrGLubyte* version; |
| 199 GL_CALL_RET(vendor, GetString(GR_GL_VENDOR)); | 198 GL_CALL_RET(vendor, GetString(GR_GL_VENDOR)); |
| 200 GL_CALL_RET(renderer, GetString(GR_GL_RENDERER)); | 199 GL_CALL_RET(renderer, GetString(GR_GL_RENDERER)); |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 | 687 |
| 689 // in case we need a temporary, trimmed copy of the src pixels | 688 // in case we need a temporary, trimmed copy of the src pixels |
| 690 #if defined(GOOGLE3) | 689 #if defined(GOOGLE3) |
| 691 // Stack frame size is limited in GOOGLE3. | 690 // Stack frame size is limited in GOOGLE3. |
| 692 SkAutoSMalloc<64 * 128> tempStorage; | 691 SkAutoSMalloc<64 * 128> tempStorage; |
| 693 #else | 692 #else |
| 694 SkAutoSMalloc<128 * 128> tempStorage; | 693 SkAutoSMalloc<128 * 128> tempStorage; |
| 695 #endif | 694 #endif |
| 696 | 695 |
| 697 // Internal format comes from the texture desc. | 696 // Internal format comes from the texture desc. |
| 698 GrGLenum internalFormat = fConfigTable[desc.fConfig].fInternalFormatTexImage
; | 697 GrGLenum internalFormat = this->glCaps().configGLFormats(desc.fConfig).fInte
rnalFormatTexImage; |
| 699 | 698 |
| 700 // External format and type come from the upload data. | 699 // External format and type come from the upload data. |
| 701 GrGLenum externalFormat = fConfigTable[dataConfig].fExternalFormatForTexImag
e; | 700 GrGLenum externalFormat = this->glCaps().configGLFormats(desc.fConfig).fExte
rnalFormatForTexImage; |
| 702 GrGLenum externalType = fConfigTable[dataConfig].fExternalType; | 701 GrGLenum externalType = this->glCaps().configGLFormats(desc.fConfig).fExtern
alType; |
| 703 | 702 |
| 704 /* | 703 /* |
| 705 * Check whether to allocate a temporary buffer for flipping y or | 704 * Check whether to allocate a temporary buffer for flipping y or |
| 706 * because our srcData has extra bytes past each row. If so, we need | 705 * because our srcData has extra bytes past each row. If so, we need |
| 707 * to trim those off here, since GL ES may not let us specify | 706 * to trim those off here, since GL ES may not let us specify |
| 708 * GL_UNPACK_ROW_LENGTH. | 707 * GL_UNPACK_ROW_LENGTH. |
| 709 */ | 708 */ |
| 710 bool restoreGLRowLength = false; | 709 bool restoreGLRowLength = false; |
| 711 bool swFlipY = false; | 710 bool swFlipY = false; |
| 712 bool glFlipY = false; | 711 bool glFlipY = false; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 SkASSERT(height <= desc.fHeight); | 819 SkASSERT(height <= desc.fHeight); |
| 821 } | 820 } |
| 822 #endif | 821 #endif |
| 823 | 822 |
| 824 // Make sure that the width and height that we pass to OpenGL | 823 // Make sure that the width and height that we pass to OpenGL |
| 825 // is a multiple of the block size. | 824 // is a multiple of the block size. |
| 826 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); | 825 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); |
| 827 | 826 |
| 828 // We only need the internal format for compressed 2D textures. There is on | 827 // We only need the internal format for compressed 2D textures. There is on |
| 829 // sized vs base internal format distinction for compressed textures. | 828 // sized vs base internal format distinction for compressed textures. |
| 830 GrGLenum internalFormat = fConfigTable[desc.fConfig].fSizedInternalFormat; | 829 GrGLenum internalFormat =this->glCaps().configGLFormats(desc.fConfig).fSized
InternalFormat; |
| 831 | 830 |
| 832 if (isNewTexture) { | 831 if (isNewTexture) { |
| 833 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 832 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
| 834 GL_ALLOC_CALL(this->glInterface(), | 833 GL_ALLOC_CALL(this->glInterface(), |
| 835 CompressedTexImage2D(target, | 834 CompressedTexImage2D(target, |
| 836 0, // level | 835 0, // level |
| 837 internalFormat, | 836 internalFormat, |
| 838 width, height, | 837 width, height, |
| 839 0, // border | 838 0, // border |
| 840 SkToInt(dataSize), | 839 SkToInt(dataSize), |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID)); | 931 GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID)); |
| 933 GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID)); | 932 GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID)); |
| 934 if (!idDesc->fRTFBOID || | 933 if (!idDesc->fRTFBOID || |
| 935 !idDesc->fMSColorRenderbufferID) { | 934 !idDesc->fMSColorRenderbufferID) { |
| 936 goto FAILED; | 935 goto FAILED; |
| 937 } | 936 } |
| 938 // All ES versions (thus far) require sized internal formats for render
buffers. | 937 // All ES versions (thus far) require sized internal formats for render
buffers. |
| 939 // TODO: Always use sized internal format? | 938 // TODO: Always use sized internal format? |
| 940 // If this rule gets more complicated, add a field to ConfigEntry rather
than logic here. | 939 // If this rule gets more complicated, add a field to ConfigEntry rather
than logic here. |
| 941 colorRenderbufferFormat = kGLES_GrGLStandard == this->glStandard() ? | 940 colorRenderbufferFormat = kGLES_GrGLStandard == this->glStandard() ? |
| 942 fConfigTable[desc.fConfig].fSize
dInternalFormat : | 941 this->glCaps().configGLFormats(desc.fConfig).fSizedI
nternalFormat : |
| 943 fConfigTable[desc.fConfig].fBase
InternalFormat; | 942 this->glCaps().configGLFormats(desc.fConfig).fBaseIn
ternalFormat; |
| 944 } else { | 943 } else { |
| 945 idDesc->fRTFBOID = idDesc->fTexFBOID; | 944 idDesc->fRTFBOID = idDesc->fTexFBOID; |
| 946 } | 945 } |
| 947 | 946 |
| 948 // below here we may bind the FBO | 947 // below here we may bind the FBO |
| 949 fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; | 948 fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
| 950 if (idDesc->fRTFBOID != idDesc->fTexFBOID) { | 949 if (idDesc->fRTFBOID != idDesc->fTexFBOID) { |
| 951 SkASSERT(desc.fSampleCnt > 0); | 950 SkASSERT(desc.fSampleCnt > 0); |
| 952 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbuffe
rID)); | 951 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbuffe
rID)); |
| 953 if (!renderbuffer_storage_msaa(*fGLContext, | 952 if (!renderbuffer_storage_msaa(*fGLContext, |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 } else { | 1185 } else { |
| 1187 format->fTotalBits = format->fStencilBits; | 1186 format->fTotalBits = format->fStencilBits; |
| 1188 } | 1187 } |
| 1189 } | 1188 } |
| 1190 } | 1189 } |
| 1191 } | 1190 } |
| 1192 | 1191 |
| 1193 int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) { | 1192 int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) { |
| 1194 static const int kSize = 16; | 1193 static const int kSize = 16; |
| 1195 SkASSERT(this->caps()->isConfigRenderable(config, false)); | 1194 SkASSERT(this->caps()->isConfigRenderable(config, false)); |
| 1196 if (ConfigEntry::kUnknown_StencilIndex == fConfigTable[config].fStencilForma
tIndex) { | 1195 if (!this->glCaps().hasStencilFormatBeenDeterminedForConfig(config)) { |
| 1197 // Default to unsupported | 1196 // Default to unsupported, set this if we find a stencil format that wor
ks. |
| 1198 fConfigTable[config].fStencilFormatIndex = ConfigEntry::kUnsupported_Ste
ncilFormatIndex; | 1197 int firstWorkingStencilFormatIndex = -1; |
| 1199 // Create color texture | 1198 // Create color texture |
| 1200 GrGLuint colorID = 0; | 1199 GrGLuint colorID = 0; |
| 1201 GL_CALL(GenTextures(1, &colorID)); | 1200 GL_CALL(GenTextures(1, &colorID)); |
| 1202 this->setScratchTextureUnit(); | 1201 this->setScratchTextureUnit(); |
| 1203 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, colorID)); | 1202 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, colorID)); |
| 1204 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | 1203 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| 1205 GR_GL_TEXTURE_MAG_FILTER, | 1204 GR_GL_TEXTURE_MAG_FILTER, |
| 1206 GR_GL_NEAREST)); | 1205 GR_GL_NEAREST)); |
| 1207 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | 1206 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| 1208 GR_GL_TEXTURE_MIN_FILTER, | 1207 GR_GL_TEXTURE_MIN_FILTER, |
| 1209 GR_GL_NEAREST)); | 1208 GR_GL_NEAREST)); |
| 1210 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | 1209 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| 1211 GR_GL_TEXTURE_WRAP_S, | 1210 GR_GL_TEXTURE_WRAP_S, |
| 1212 GR_GL_CLAMP_TO_EDGE)); | 1211 GR_GL_CLAMP_TO_EDGE)); |
| 1213 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | 1212 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| 1214 GR_GL_TEXTURE_WRAP_T, | 1213 GR_GL_TEXTURE_WRAP_T, |
| 1215 GR_GL_CLAMP_TO_EDGE)); | 1214 GR_GL_CLAMP_TO_EDGE)); |
| 1216 | 1215 |
| 1217 GrGLenum internalFormat = fConfigTable[config].fInternalFormatTexImage; | 1216 const GrGLCaps::ConfigFormats colorFormats = this->glCaps().configGLForm
ats(config); |
| 1218 GrGLenum externalFormat = fConfigTable[config].fExternalFormatForTexImag
e; | |
| 1219 GrGLenum externalType = fConfigTable[config].fExternalType; | |
| 1220 | 1217 |
| 1221 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1218 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
| 1222 GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D, | 1219 GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D, |
| 1223 0, | 1220 0, |
| 1224 internalFormat, | 1221 colorFormats.fInternalForm
atTexImage, |
| 1225 kSize, | 1222 kSize, |
| 1226 kSize, | 1223 kSize, |
| 1227 0, | 1224 0, |
| 1228 externalFormat, | 1225 colorFormats.fExternalForm
atForTexImage, |
| 1229 externalType, | 1226 colorFormats.fExternalType
, |
| 1230 NULL)); | 1227 NULL)); |
| 1231 if (GR_GL_NO_ERROR != GR_GL_GET_ERROR(this->glInterface())) { | 1228 if (GR_GL_NO_ERROR != CHECK_ALLOC_ERROR(this->glInterface())) { |
| 1232 GL_CALL(DeleteTextures(1, &colorID)); | 1229 GL_CALL(DeleteTextures(1, &colorID)); |
| 1233 return ConfigEntry::kUnsupported_StencilFormatIndex; | 1230 return -1; |
| 1234 } | 1231 } |
| 1235 | 1232 |
| 1236 // unbind the texture from the texture unit before binding it to the fra
me buffer | 1233 // unbind the texture from the texture unit before binding it to the fra
me buffer |
| 1237 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0)); | 1234 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0)); |
| 1238 | 1235 |
| 1239 // Create Framebuffer | 1236 // Create Framebuffer |
| 1240 GrGLuint fb = 0; | 1237 GrGLuint fb = 0; |
| 1241 GL_CALL(GenFramebuffers(1, &fb)); | 1238 GL_CALL(GenFramebuffers(1, &fb)); |
| 1242 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fb)); | 1239 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fb)); |
| 1243 fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; | 1240 fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
| 1244 GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, | 1241 GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, |
| 1245 GR_GL_COLOR_ATTACHMENT0, | 1242 GR_GL_COLOR_ATTACHMENT0, |
| 1246 GR_GL_TEXTURE_2D, | 1243 GR_GL_TEXTURE_2D, |
| 1247 colorID, | 1244 colorID, |
| 1248 0)); | 1245 0)); |
| 1246 GrGLuint sbRBID = 0; |
| 1247 GL_CALL(GenRenderbuffers(1, &sbRBID)); |
| 1249 | 1248 |
| 1250 // look over formats till I find a compatible one | 1249 // look over formats till I find a compatible one |
| 1251 int stencilFmtCnt = this->glCaps().stencilFormats().count(); | 1250 int stencilFmtCnt = this->glCaps().stencilFormats().count(); |
| 1252 GrGLuint sbRBID = 0; | 1251 if (sbRBID) { |
| 1253 for (int i = 0; i < stencilFmtCnt; ++i) { | |
| 1254 const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats(
)[i]; | |
| 1255 | |
| 1256 GL_CALL(GenRenderbuffers(1, &sbRBID)); | |
| 1257 if (!sbRBID) { | |
| 1258 break; | |
| 1259 } | |
| 1260 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbRBID)); | 1252 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbRBID)); |
| 1261 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1253 for (int i = 0; i < stencilFmtCnt && sbRBID; ++i) { |
| 1262 GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERB
UFFER, | 1254 const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilForm
ats()[i]; |
| 1263 sFmt.fInterna
lFormat, | 1255 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
| 1264 kSize, kSize)
); | 1256 GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_REN
DERBUFFER, |
| 1265 if (GR_GL_NO_ERROR == GR_GL_GET_ERROR(this->glInterface())) { | 1257 sFmt.fInt
ernalFormat, |
| 1266 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, | 1258 kSize, kS
ize)); |
| 1267 GR_GL_STENCIL_ATTACHMENT, | 1259 if (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface())) { |
| 1268 GR_GL_RENDERBUFFER, sbRBID)); | |
| 1269 if (sFmt.fPacked) { | |
| 1270 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, | 1260 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
| 1271 GR_GL_DEPTH_ATTACHMENT, | 1261 GR_GL_STENCIL_ATTACHMENT, |
| 1272 GR_GL_RENDERBUFFER, sbRBID))
; | 1262 GR_GL_RENDERBUFFER, sbRBID))
; |
| 1273 } else { | 1263 if (sFmt.fPacked) { |
| 1274 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, | 1264 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
| 1275 GR_GL_DEPTH_ATTACHMENT, | 1265 GR_GL_DEPTH_ATTACHMENT, |
| 1276 GR_GL_RENDERBUFFER, 0)); | 1266 GR_GL_RENDERBUFFER, sbRB
ID)); |
| 1277 } | 1267 } else { |
| 1278 GrGLenum status; | 1268 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
| 1279 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); | 1269 GR_GL_DEPTH_ATTACHMENT, |
| 1280 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { | 1270 GR_GL_RENDERBUFFER, 0)); |
| 1271 } |
| 1272 GrGLenum status; |
| 1273 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER
)); |
| 1274 if (status == GR_GL_FRAMEBUFFER_COMPLETE) { |
| 1275 firstWorkingStencilFormatIndex = i; |
| 1276 break; |
| 1277 } |
| 1281 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, | 1278 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
| 1282 GR_GL_STENCIL_ATTACHMENT, | 1279 GR_GL_STENCIL_ATTACHMENT, |
| 1283 GR_GL_RENDERBUFFER, 0)); | 1280 GR_GL_RENDERBUFFER, 0)); |
| 1284 if (sFmt.fPacked) { | 1281 if (sFmt.fPacked) { |
| 1285 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, | 1282 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
| 1286 GR_GL_DEPTH_ATTACHMENT, | 1283 GR_GL_DEPTH_ATTACHMENT, |
| 1287 GR_GL_RENDERBUFFER, 0)); | 1284 GR_GL_RENDERBUFFER, 0)); |
| 1288 } | 1285 } |
| 1289 } else { | |
| 1290 fConfigTable[config].fStencilFormatIndex = i; | |
| 1291 break; | |
| 1292 } | 1286 } |
| 1293 } | 1287 } |
| 1294 sbRBID = 0; | 1288 GL_CALL(DeleteRenderbuffers(1, &sbRBID)); |
| 1295 } | 1289 } |
| 1296 GL_CALL(DeleteTextures(1, &colorID)); | 1290 GL_CALL(DeleteTextures(1, &colorID)); |
| 1297 GL_CALL(DeleteRenderbuffers(1, &sbRBID)); | |
| 1298 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); | 1291 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); |
| 1299 GL_CALL(DeleteFramebuffers(1, &fb)); | 1292 GL_CALL(DeleteFramebuffers(1, &fb)); |
| 1293 fGLContext->caps()->setStencilFormatIndexForConfig(config, firstWorkingS
tencilFormatIndex); |
| 1300 } | 1294 } |
| 1301 SkASSERT(ConfigEntry::kUnknown_StencilIndex != fConfigTable[config].fStencil
FormatIndex); | 1295 int index; |
| 1302 return fConfigTable[config].fStencilFormatIndex; | 1296 return this->glCaps().getStencilFormatIndexForConfig(config, &index) ? index
: -1; |
| 1303 } | 1297 } |
| 1304 | 1298 |
| 1305 GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen
derTarget* rt, | 1299 GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen
derTarget* rt, |
| 1306 int width, | 1300 int width, |
| 1307 int height)
{ | 1301 int height)
{ |
| 1308 // All internally created RTs are also textures. We don't create | 1302 // All internally created RTs are also textures. We don't create |
| 1309 // SBs for a client's standalone RT (that is a RT that isn't also a texture)
. | 1303 // SBs for a client's standalone RT (that is a RT that isn't also a texture)
. |
| 1310 SkASSERT(rt->asTexture()); | 1304 SkASSERT(rt->asTexture()); |
| 1311 SkASSERT(width >= rt->width()); | 1305 SkASSERT(width >= rt->width()); |
| 1312 SkASSERT(height >= rt->height()); | 1306 SkASSERT(height >= rt->height()); |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1959 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(surface->asRenderTarg
et()); | 1953 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(surface->asRenderTarg
et()); |
| 1960 if (!tgt) { | 1954 if (!tgt) { |
| 1961 return false; | 1955 return false; |
| 1962 } | 1956 } |
| 1963 | 1957 |
| 1964 // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pi
xels. | 1958 // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pi
xels. |
| 1965 if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { | 1959 if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { |
| 1966 return false; | 1960 return false; |
| 1967 } | 1961 } |
| 1968 | 1962 |
| 1969 GrGLenum format = fConfigTable[config].fExternalFormat; | 1963 GrGLenum format = this->glCaps().configGLFormats(config).fExternalFormat; |
| 1970 GrGLenum type = fConfigTable[config].fExternalType; | 1964 GrGLenum type = this->glCaps().configGLFormats(config).fExternalType; |
| 1971 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); | 1965 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); |
| 1972 | 1966 |
| 1973 // resolve the render target if necessary | 1967 // resolve the render target if necessary |
| 1974 switch (tgt->getResolveType()) { | 1968 switch (tgt->getResolveType()) { |
| 1975 case GrGLRenderTarget::kCantResolve_ResolveType: | 1969 case GrGLRenderTarget::kCantResolve_ResolveType: |
| 1976 return false; | 1970 return false; |
| 1977 case GrGLRenderTarget::kAutoResolves_ResolveType: | 1971 case GrGLRenderTarget::kAutoResolves_ResolveType: |
| 1978 this->flushRenderTarget(tgt, &SkIRect::EmptyIRect()); | 1972 this->flushRenderTarget(tgt, &SkIRect::EmptyIRect()); |
| 1979 break; | 1973 break; |
| 1980 case GrGLRenderTarget::kCanResolve_ResolveType: | 1974 case GrGLRenderTarget::kCanResolve_ResolveType: |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2575 case GrPipelineBuilder::kBoth_DrawFace: | 2569 case GrPipelineBuilder::kBoth_DrawFace: |
| 2576 GL_CALL(Disable(GR_GL_CULL_FACE)); | 2570 GL_CALL(Disable(GR_GL_CULL_FACE)); |
| 2577 break; | 2571 break; |
| 2578 default: | 2572 default: |
| 2579 SkFAIL("Unknown draw face."); | 2573 SkFAIL("Unknown draw face."); |
| 2580 } | 2574 } |
| 2581 fHWDrawFace = face; | 2575 fHWDrawFace = face; |
| 2582 } | 2576 } |
| 2583 } | 2577 } |
| 2584 | 2578 |
| 2585 void GrGLGpu::generateConfigTable() { | |
| 2586 fConfigTable[kUnknown_GrPixelConfig].fBaseInternalFormat = 0; | |
| 2587 fConfigTable[kUnknown_GrPixelConfig].fSizedInternalFormat = 0; | |
| 2588 fConfigTable[kUnknown_GrPixelConfig].fExternalFormat = 0; | |
| 2589 fConfigTable[kUnknown_GrPixelConfig].fExternalType = 0; | |
| 2590 | |
| 2591 fConfigTable[kRGBA_8888_GrPixelConfig].fBaseInternalFormat = GR_GL_RGBA; | |
| 2592 fConfigTable[kRGBA_8888_GrPixelConfig].fSizedInternalFormat = GR_GL_RGBA8; | |
| 2593 fConfigTable[kRGBA_8888_GrPixelConfig].fExternalFormat = GR_GL_RGBA; | |
| 2594 fConfigTable[kRGBA_8888_GrPixelConfig].fExternalType = GR_GL_UNSIGNED_BYTE; | |
| 2595 | |
| 2596 if (this->glCaps().bgraIsInternalFormat()) { | |
| 2597 fConfigTable[kBGRA_8888_GrPixelConfig].fBaseInternalFormat = GR_GL_BGRA; | |
| 2598 fConfigTable[kBGRA_8888_GrPixelConfig].fSizedInternalFormat = GR_GL_BGRA
8; | |
| 2599 } else { | |
| 2600 fConfigTable[kBGRA_8888_GrPixelConfig].fBaseInternalFormat = GR_GL_RGBA; | |
| 2601 fConfigTable[kBGRA_8888_GrPixelConfig].fSizedInternalFormat = GR_GL_RGBA
8; | |
| 2602 } | |
| 2603 fConfigTable[kBGRA_8888_GrPixelConfig].fExternalFormat= GR_GL_BGRA; | |
| 2604 fConfigTable[kBGRA_8888_GrPixelConfig].fExternalType = GR_GL_UNSIGNED_BYTE; | |
| 2605 | |
| 2606 | |
| 2607 fConfigTable[kSRGBA_8888_GrPixelConfig].fBaseInternalFormat = GR_GL_SRGB_ALP
HA; | |
| 2608 fConfigTable[kSRGBA_8888_GrPixelConfig].fSizedInternalFormat = GR_GL_SRGB8_A
LPHA8; | |
| 2609 // GL does not do srgb<->rgb conversions when transferring between cpu and g
pu. Thus, the | |
| 2610 // external format is GL_RGBA. See below for note about ES2.0 and glTex[Sub]
Image. | |
| 2611 fConfigTable[kSRGBA_8888_GrPixelConfig].fExternalFormat = GR_GL_RGBA; | |
| 2612 fConfigTable[kSRGBA_8888_GrPixelConfig].fExternalType = GR_GL_UNSIGNED_BYTE; | |
| 2613 | |
| 2614 | |
| 2615 fConfigTable[kRGB_565_GrPixelConfig].fBaseInternalFormat = GR_GL_RGB; | |
| 2616 if (this->glCaps().ES2CompatibilitySupport()) { | |
| 2617 fConfigTable[kRGB_565_GrPixelConfig].fSizedInternalFormat = GR_GL_RGB565
; | |
| 2618 } else { | |
| 2619 fConfigTable[kRGB_565_GrPixelConfig].fSizedInternalFormat = GR_GL_RGB5; | |
| 2620 } | |
| 2621 fConfigTable[kRGB_565_GrPixelConfig].fExternalFormat = GR_GL_RGB; | |
| 2622 fConfigTable[kRGB_565_GrPixelConfig].fExternalType = GR_GL_UNSIGNED_SHORT_5_
6_5; | |
| 2623 | |
| 2624 fConfigTable[kRGBA_4444_GrPixelConfig].fBaseInternalFormat = GR_GL_RGBA; | |
| 2625 fConfigTable[kRGBA_4444_GrPixelConfig].fSizedInternalFormat = GR_GL_RGBA4; | |
| 2626 fConfigTable[kRGBA_4444_GrPixelConfig].fExternalFormat = GR_GL_RGBA; | |
| 2627 fConfigTable[kRGBA_4444_GrPixelConfig].fExternalType = GR_GL_UNSIGNED_SHORT_
4_4_4_4; | |
| 2628 | |
| 2629 | |
| 2630 if (this->glCaps().textureRedSupport()) { | |
| 2631 fConfigTable[kAlpha_8_GrPixelConfig].fBaseInternalFormat = GR_GL_RED; | |
| 2632 fConfigTable[kAlpha_8_GrPixelConfig].fSizedInternalFormat = GR_GL_R8; | |
| 2633 fConfigTable[kAlpha_8_GrPixelConfig].fExternalFormat = GR_GL_RED; | |
| 2634 } else { | |
| 2635 fConfigTable[kAlpha_8_GrPixelConfig].fBaseInternalFormat = GR_GL_ALPHA; | |
| 2636 fConfigTable[kAlpha_8_GrPixelConfig].fSizedInternalFormat = GR_GL_ALPHA8
; | |
| 2637 fConfigTable[kAlpha_8_GrPixelConfig].fExternalFormat = GR_GL_ALPHA; | |
| 2638 } | |
| 2639 fConfigTable[kAlpha_8_GrPixelConfig].fExternalType = GR_GL_UNSIGNED_BYTE; | |
| 2640 | |
| 2641 fConfigTable[kRGBA_float_GrPixelConfig].fBaseInternalFormat = GR_GL_RGBA; | |
| 2642 fConfigTable[kRGBA_float_GrPixelConfig].fSizedInternalFormat = GR_GL_RGBA32F
; | |
| 2643 fConfigTable[kRGBA_float_GrPixelConfig].fExternalFormat = GR_GL_RGBA; | |
| 2644 fConfigTable[kRGBA_float_GrPixelConfig].fExternalType = GR_GL_FLOAT; | |
| 2645 | |
| 2646 if (this->glCaps().textureRedSupport()) { | |
| 2647 fConfigTable[kAlpha_half_GrPixelConfig].fBaseInternalFormat = GR_GL_RED; | |
| 2648 fConfigTable[kAlpha_half_GrPixelConfig].fSizedInternalFormat = GR_GL_R16
F; | |
| 2649 fConfigTable[kAlpha_half_GrPixelConfig].fExternalFormat = GR_GL_RED; | |
| 2650 } else { | |
| 2651 fConfigTable[kAlpha_half_GrPixelConfig].fBaseInternalFormat = GR_GL_ALPH
A; | |
| 2652 fConfigTable[kAlpha_half_GrPixelConfig].fSizedInternalFormat = GR_GL_ALP
HA16F; | |
| 2653 fConfigTable[kAlpha_half_GrPixelConfig].fExternalFormat = GR_GL_ALPHA; | |
| 2654 } | |
| 2655 if (kGL_GrGLStandard == this->glStandard() || this->glVersion() >= GR_GL_VER
(3, 0)) { | |
| 2656 fConfigTable[kAlpha_half_GrPixelConfig].fExternalType = GR_GL_HALF_FLOAT
; | |
| 2657 } else { | |
| 2658 fConfigTable[kAlpha_half_GrPixelConfig].fExternalType = GR_GL_HALF_FLOAT
_OES; | |
| 2659 } | |
| 2660 | |
| 2661 fConfigTable[kRGBA_half_GrPixelConfig].fBaseInternalFormat = GR_GL_RGBA; | |
| 2662 fConfigTable[kRGBA_half_GrPixelConfig].fSizedInternalFormat = GR_GL_RGBA16F; | |
| 2663 fConfigTable[kRGBA_half_GrPixelConfig].fExternalFormat = GR_GL_RGBA; | |
| 2664 if (kGL_GrGLStandard == this->glStandard() || this->glVersion() >= GR_GL_VER
(3, 0)) { | |
| 2665 fConfigTable[kRGBA_half_GrPixelConfig].fExternalType = GR_GL_HALF_FLOAT; | |
| 2666 } else { | |
| 2667 fConfigTable[kRGBA_half_GrPixelConfig].fExternalType = GR_GL_HALF_FLOAT_
OES; | |
| 2668 } | |
| 2669 | |
| 2670 // No sized/unsized internal format distinction for compressed formats, no e
xternal format. | |
| 2671 | |
| 2672 fConfigTable[kIndex_8_GrPixelConfig].fBaseInternalFormat = GR_GL_PALETTE8_RG
BA8; | |
| 2673 fConfigTable[kIndex_8_GrPixelConfig].fSizedInternalFormat = GR_GL_PALETTE8_R
GBA8; | |
| 2674 fConfigTable[kIndex_8_GrPixelConfig].fExternalFormat = 0; | |
| 2675 fConfigTable[kIndex_8_GrPixelConfig].fExternalType = 0; | |
| 2676 | |
| 2677 switch(this->glCaps().latcAlias()) { | |
| 2678 case GrGLCaps::kLATC_LATCAlias: | |
| 2679 fConfigTable[kLATC_GrPixelConfig].fBaseInternalFormat = | |
| 2680 GR_GL_COMPRESSED_LUMINANCE_LATC1; | |
| 2681 fConfigTable[kLATC_GrPixelConfig].fSizedInternalFormat = | |
| 2682 GR_GL_COMPRESSED_LUMINANCE_LATC1; | |
| 2683 break; | |
| 2684 case GrGLCaps::kRGTC_LATCAlias: | |
| 2685 fConfigTable[kLATC_GrPixelConfig].fBaseInternalFormat = GR_GL_COMPRE
SSED_RED_RGTC1; | |
| 2686 fConfigTable[kLATC_GrPixelConfig].fSizedInternalFormat = GR_GL_COMPR
ESSED_RED_RGTC1; | |
| 2687 break; | |
| 2688 case GrGLCaps::k3DC_LATCAlias: | |
| 2689 fConfigTable[kLATC_GrPixelConfig].fBaseInternalFormat = GR_GL_COMPRE
SSED_3DC_X; | |
| 2690 fConfigTable[kLATC_GrPixelConfig].fSizedInternalFormat = GR_GL_COMPR
ESSED_3DC_X; | |
| 2691 break; | |
| 2692 } | |
| 2693 fConfigTable[kLATC_GrPixelConfig].fExternalFormat = 0; | |
| 2694 fConfigTable[kLATC_GrPixelConfig].fExternalType = 0; | |
| 2695 | |
| 2696 fConfigTable[kETC1_GrPixelConfig].fBaseInternalFormat = GR_GL_COMPRESSED_ETC
1_RGB8; | |
| 2697 fConfigTable[kETC1_GrPixelConfig].fSizedInternalFormat = GR_GL_COMPRESSED_ET
C1_RGB8; | |
| 2698 fConfigTable[kETC1_GrPixelConfig].fExternalFormat = 0; | |
| 2699 fConfigTable[kETC1_GrPixelConfig].fExternalType = 0; | |
| 2700 | |
| 2701 fConfigTable[kR11_EAC_GrPixelConfig].fBaseInternalFormat = GR_GL_COMPRESSED_
R11_EAC; | |
| 2702 fConfigTable[kR11_EAC_GrPixelConfig].fSizedInternalFormat = GR_GL_COMPRESSED
_R11_EAC; | |
| 2703 fConfigTable[kR11_EAC_GrPixelConfig].fExternalFormat = 0; | |
| 2704 fConfigTable[kR11_EAC_GrPixelConfig].fExternalType = 0; | |
| 2705 | |
| 2706 fConfigTable[kASTC_12x12_GrPixelConfig].fBaseInternalFormat = GR_GL_COMPRESS
ED_RGBA_ASTC_12x12; | |
| 2707 fConfigTable[kASTC_12x12_GrPixelConfig].fSizedInternalFormat = GR_GL_COMPRES
SED_RGBA_ASTC_12x12; | |
| 2708 fConfigTable[kASTC_12x12_GrPixelConfig].fExternalFormat = 0; | |
| 2709 fConfigTable[kASTC_12x12_GrPixelConfig].fExternalType = 0; | |
| 2710 | |
| 2711 // Bulk populate the texture internal/external formats here and then deal wi
th exceptions below. | |
| 2712 | |
| 2713 // ES 2.0 requires that the internal/external formats match. | |
| 2714 bool useSizedFormats = (kGL_GrGLStandard == this->glStandard() || | |
| 2715 this->glVersion() >= GR_GL_VER(3,0)); | |
| 2716 for (int i = 0; i < kGrPixelConfigCnt; ++i) { | |
| 2717 // Almost always we want to pass fExternalFormat as the <format> param t
o glTex[Sub]Image. | |
| 2718 fConfigTable[i].fExternalFormatForTexImage = fConfigTable[i].fExternalFo
rmat; | |
| 2719 fConfigTable[i].fInternalFormatTexImage = useSizedFormats ? | |
| 2720 fConfigTable[i].fSizedIn
ternalFormat : | |
| 2721 fConfigTable[i].fBaseInt
ernalFormat; | |
| 2722 } | |
| 2723 // OpenGL ES 2.0 + GL_EXT_sRGB allows GL_SRGB_ALPHA to be specified as the <
format> | |
| 2724 // param to Tex(Sub)Image. ES 2.0 requires the <internalFormat> and <format>
params to match. | |
| 2725 // Thus, on ES 2.0 we will use GL_SRGB_ALPHA as the <format> param. | |
| 2726 // On OpenGL and ES 3.0+ GL_SRGB_ALPHA does not work for the <format> param
to glTexImage. | |
| 2727 if (this->glStandard() == kGLES_GrGLStandard && this->glVersion() == GR_GL_V
ER(2,0)) { | |
| 2728 fConfigTable[kSRGBA_8888_GrPixelConfig].fExternalFormatForTexImage = GR_
GL_SRGB_ALPHA; | |
| 2729 } | |
| 2730 | |
| 2731 // If BGRA is supported as an internal format it must always be specified to
glTex[Sub]Image | |
| 2732 // as a base format. | |
| 2733 // GL_EXT_texture_format_BGRA8888: | |
| 2734 // This extension GL_BGRA as an unsized internal format. However, it is
written against ES | |
| 2735 // 2.0 and therefore doesn't define a value for GL_BGRA8 as ES 2.0 uses
unsized internal | |
| 2736 // formats. | |
| 2737 // GL_APPLE_texture_format_BGRA8888: | |
| 2738 // ES 2.0: the extension makes BGRA an external format but not an intern
al format. | |
| 2739 // ES 3.0: the extension explicitly states GL_BGRA8 is not a valid inter
nal format for | |
| 2740 // glTexImage (just for glTexStorage). | |
| 2741 if (useSizedFormats && this->glCaps().bgraIsInternalFormat()) { | |
| 2742 fConfigTable[kBGRA_8888_GrPixelConfig].fInternalFormatTexImage = GR_GL_B
GRA; | |
| 2743 } | |
| 2744 | |
| 2745 #ifdef SK_DEBUG | |
| 2746 // Make sure we initialized everything. | |
| 2747 ConfigEntry defaultEntry; | |
| 2748 for (int i = 0; i < kGrPixelConfigCnt; ++i) { | |
| 2749 SkASSERT(defaultEntry.fBaseInternalFormat != fConfigTable[i].fBaseIntern
alFormat); | |
| 2750 SkASSERT(defaultEntry.fSizedInternalFormat != fConfigTable[i].fSizedInte
rnalFormat); | |
| 2751 SkASSERT(defaultEntry.fExternalFormat != fConfigTable[i].fExternalFormat
); | |
| 2752 SkASSERT(defaultEntry.fExternalType != fConfigTable[i].fExternalType); | |
| 2753 } | |
| 2754 #endif | |
| 2755 } | |
| 2756 | |
| 2757 void GrGLGpu::setTextureUnit(int unit) { | 2579 void GrGLGpu::setTextureUnit(int unit) { |
| 2758 SkASSERT(unit >= 0 && unit < fHWBoundTextureUniqueIDs.count()); | 2580 SkASSERT(unit >= 0 && unit < fHWBoundTextureUniqueIDs.count()); |
| 2759 if (unit != fHWActiveTextureUnitIdx) { | 2581 if (unit != fHWActiveTextureUnitIdx) { |
| 2760 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit)); | 2582 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit)); |
| 2761 fHWActiveTextureUnitIdx = unit; | 2583 fHWActiveTextureUnitIdx = unit; |
| 2762 } | 2584 } |
| 2763 } | 2585 } |
| 2764 | 2586 |
| 2765 void GrGLGpu::setScratchTextureUnit() { | 2587 void GrGLGpu::setScratchTextureUnit() { |
| 2766 // Bind the last texture unit since it is the least likely to be used by GrG
LProgram. | 2588 // Bind the last texture unit since it is the least likely to be used by GrG
LProgram. |
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3441 info->fID = 0; | 3263 info->fID = 0; |
| 3442 GL_CALL(GenTextures(1, &info->fID)); | 3264 GL_CALL(GenTextures(1, &info->fID)); |
| 3443 GL_CALL(ActiveTexture(GR_GL_TEXTURE0)); | 3265 GL_CALL(ActiveTexture(GR_GL_TEXTURE0)); |
| 3444 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1)); | 3266 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1)); |
| 3445 GL_CALL(BindTexture(info->fTarget, info->fID)); | 3267 GL_CALL(BindTexture(info->fTarget, info->fID)); |
| 3446 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST
)); | 3268 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST
)); |
| 3447 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST
)); | 3269 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST
)); |
| 3448 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_ED
GE)); | 3270 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_ED
GE)); |
| 3449 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_ED
GE)); | 3271 GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_ED
GE)); |
| 3450 | 3272 |
| 3451 GrGLenum internalFormat = fConfigTable[config].fInternalFormatTexImage; | 3273 GrGLenum internalFormat = this->glCaps().configGLFormats(config).fInternalFo
rmatTexImage; |
| 3452 GrGLenum externalFormat = fConfigTable[config].fExternalFormatForTexImage; | 3274 GrGLenum externalFormat = this->glCaps().configGLFormats(config).fExternalFo
rmatForTexImage; |
| 3453 GrGLenum externalType = fConfigTable[config].fExternalType; | 3275 GrGLenum externalType = this->glCaps().configGLFormats(config).fExternalType
; |
| 3454 | 3276 |
| 3455 GL_CALL(TexImage2D(info->fTarget, 0, internalFormat, w, h, 0, externalFormat
, | 3277 GL_CALL(TexImage2D(info->fTarget, 0, internalFormat, w, h, 0, externalFormat
, |
| 3456 externalType, pixels)); | 3278 externalType, pixels)); |
| 3457 | 3279 |
| 3458 #ifdef SK_IGNORE_GL_TEXTURE_TARGET | 3280 #ifdef SK_IGNORE_GL_TEXTURE_TARGET |
| 3459 GrGLuint id = info->fID; | 3281 GrGLuint id = info->fID; |
| 3460 delete info; | 3282 delete info; |
| 3461 return id; | 3283 return id; |
| 3462 #else | 3284 #else |
| 3463 return reinterpret_cast<GrBackendObject>(info); | 3285 return reinterpret_cast<GrBackendObject>(info); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3549 this->setVertexArrayID(gpu, 0); | 3371 this->setVertexArrayID(gpu, 0); |
| 3550 } | 3372 } |
| 3551 int attrCount = gpu->glCaps().maxVertexAttributes(); | 3373 int attrCount = gpu->glCaps().maxVertexAttributes(); |
| 3552 if (fDefaultVertexArrayAttribState.count() != attrCount) { | 3374 if (fDefaultVertexArrayAttribState.count() != attrCount) { |
| 3553 fDefaultVertexArrayAttribState.resize(attrCount); | 3375 fDefaultVertexArrayAttribState.resize(attrCount); |
| 3554 } | 3376 } |
| 3555 attribState = &fDefaultVertexArrayAttribState; | 3377 attribState = &fDefaultVertexArrayAttribState; |
| 3556 } | 3378 } |
| 3557 return attribState; | 3379 return attribState; |
| 3558 } | 3380 } |
| OLD | NEW |