Chromium Code Reviews| 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 #include "GrGLGpu.h" | 8 #include "GrGLGpu.h" |
| 9 #include "GrGLBuffer.h" | 9 #include "GrGLBuffer.h" |
| 10 #include "GrGLGLSL.h" | 10 #include "GrGLGLSL.h" |
| (...skipping 1963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1974 GL_CALL(MinSampleShading(minSampleShading)); | 1974 GL_CALL(MinSampleShading(minSampleShading)); |
| 1975 } | 1975 } |
| 1976 else { | 1976 else { |
| 1977 GL_CALL(Disable(GR_GL_SAMPLE_SHADING)); | 1977 GL_CALL(Disable(GR_GL_SAMPLE_SHADING)); |
| 1978 } | 1978 } |
| 1979 fHWMinSampleShading = minSampleShading; | 1979 fHWMinSampleShading = minSampleShading; |
| 1980 } | 1980 } |
| 1981 } | 1981 } |
| 1982 | 1982 |
| 1983 bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso r& primProc) { | 1983 bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso r& primProc) { |
| 1984 SkAutoTUnref<GrGLProgram> program(fProgramCache->refProgram(this, pipeline, primProc)); | |
| 1985 if (!program) { | |
| 1986 GrCapsDebugf(this->caps(), "Failed to create program!\n"); | |
| 1987 return false; | |
| 1988 } | |
| 1989 | |
| 1990 program->generateMipmaps(primProc, pipeline); | |
| 1991 | |
| 1984 GrXferProcessor::BlendInfo blendInfo; | 1992 GrXferProcessor::BlendInfo blendInfo; |
| 1985 pipeline.getXferProcessor().getBlendInfo(&blendInfo); | 1993 pipeline.getXferProcessor().getBlendInfo(&blendInfo); |
| 1986 | 1994 |
| 1987 this->flushColorWrite(blendInfo.fWriteColor); | 1995 this->flushColorWrite(blendInfo.fWriteColor); |
| 1988 this->flushDrawFace(pipeline.getDrawFace()); | 1996 this->flushDrawFace(pipeline.getDrawFace()); |
| 1989 this->flushMinSampleShading(primProc.getSampleShading()); | 1997 this->flushMinSampleShading(primProc.getSampleShading()); |
| 1990 | 1998 |
| 1991 SkAutoTUnref<GrGLProgram> program(fProgramCache->refProgram(this, pipeline, primProc)); | |
| 1992 if (!program) { | |
| 1993 GrCapsDebugf(this->caps(), "Failed to create program!\n"); | |
| 1994 return false; | |
| 1995 } | |
| 1996 | |
| 1997 GrGLuint programID = program->programID(); | 1999 GrGLuint programID = program->programID(); |
| 1998 if (fHWProgramID != programID) { | 2000 if (fHWProgramID != programID) { |
| 1999 GL_CALL(UseProgram(programID)); | 2001 GL_CALL(UseProgram(programID)); |
| 2000 fHWProgramID = programID; | 2002 fHWProgramID = programID; |
| 2001 } | 2003 } |
| 2002 | 2004 |
| 2003 if (blendInfo.fWriteColor) { | 2005 if (blendInfo.fWriteColor) { |
| 2004 // Swizzle the blend to match what the shader will output. | 2006 // Swizzle the blend to match what the shader will output. |
| 2005 const GrSwizzle& swizzle = this->glCaps().glslCaps()->configOutputSwizzl e( | 2007 const GrSwizzle& swizzle = this->glCaps().glslCaps()->configOutputSwizzl e( |
| 2006 pipeline.getRenderTarget()->config()); | 2008 pipeline.getRenderTarget()->config()); |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2638 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { | 2640 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { |
| 2639 SkDebugf("GrGLGpu::flushRenderTarget glCheckFramebufferStatus %x \n", status); | 2641 SkDebugf("GrGLGpu::flushRenderTarget glCheckFramebufferStatus %x \n", status); |
| 2640 } | 2642 } |
| 2641 } | 2643 } |
| 2642 #endif | 2644 #endif |
| 2643 fHWBoundRenderTargetUniqueID = rtID; | 2645 fHWBoundRenderTargetUniqueID = rtID; |
| 2644 this->flushViewport(target->getViewport()); | 2646 this->flushViewport(target->getViewport()); |
| 2645 } | 2647 } |
| 2646 | 2648 |
| 2647 if (this->glCaps().srgbWriteControl()) { | 2649 if (this->glCaps().srgbWriteControl()) { |
| 2648 bool enableSRGBWrite = GrPixelConfigIsSRGB(target->config()) && !disable SRGB; | 2650 setFramebufferSRGB(GrPixelConfigIsSRGB(target->config()) && !disableSRGB ); |
| 2649 if (enableSRGBWrite && kYes_TriState != fHWSRGBFramebuffer) { | |
| 2650 GL_CALL(Enable(GR_GL_FRAMEBUFFER_SRGB)); | |
| 2651 fHWSRGBFramebuffer = kYes_TriState; | |
| 2652 } else if (!enableSRGBWrite && kNo_TriState != fHWSRGBFramebuffer) { | |
| 2653 GL_CALL(Disable(GR_GL_FRAMEBUFFER_SRGB)); | |
| 2654 fHWSRGBFramebuffer = kNo_TriState; | |
| 2655 } | |
| 2656 } | 2651 } |
| 2657 | 2652 |
| 2658 this->didWriteToSurface(target, bounds); | 2653 this->didWriteToSurface(target, bounds); |
| 2659 } | 2654 } |
| 2660 | 2655 |
| 2656 void GrGLGpu::setFramebufferSRGB(bool enable) { | |
|
bsalomon
2016/05/31 16:35:02
Just for consistency, could we call this flushFram
Brian Osman
2016/05/31 17:33:04
Done.
| |
| 2657 if (!this->glCaps().srgbWriteControl()) { | |
| 2658 return; | |
| 2659 } | |
| 2660 | |
| 2661 if (enable && kYes_TriState != fHWSRGBFramebuffer) { | |
| 2662 GL_CALL(Enable(GR_GL_FRAMEBUFFER_SRGB)); | |
| 2663 fHWSRGBFramebuffer = kYes_TriState; | |
| 2664 } else if (!enable && kNo_TriState != fHWSRGBFramebuffer) { | |
| 2665 GL_CALL(Disable(GR_GL_FRAMEBUFFER_SRGB)); | |
| 2666 fHWSRGBFramebuffer = kNo_TriState; | |
| 2667 } | |
| 2668 } | |
| 2669 | |
| 2661 void GrGLGpu::flushViewport(const GrGLIRect& viewport) { | 2670 void GrGLGpu::flushViewport(const GrGLIRect& viewport) { |
| 2662 if (fHWViewport != viewport) { | 2671 if (fHWViewport != viewport) { |
| 2663 viewport.pushToGLViewport(this->glInterface()); | 2672 viewport.pushToGLViewport(this->glInterface()); |
| 2664 fHWViewport = viewport; | 2673 fHWViewport = viewport; |
| 2665 } | 2674 } |
| 2666 } | 2675 } |
| 2667 | 2676 |
| 2668 GrGLenum gPrimitiveType2GLMode[] = { | 2677 GrGLenum gPrimitiveType2GLMode[] = { |
| 2669 GR_GL_TRIANGLES, | 2678 GR_GL_TRIANGLES, |
| 2670 GR_GL_TRIANGLE_STRIP, | 2679 GR_GL_TRIANGLE_STRIP, |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3131 this->setTextureUnit(unitIdx); | 3140 this->setTextureUnit(unitIdx); |
| 3132 GL_CALL(BindTexture(target, texture->textureID())); | 3141 GL_CALL(BindTexture(target, texture->textureID())); |
| 3133 fHWBoundTextureUniqueIDs[unitIdx] = textureID; | 3142 fHWBoundTextureUniqueIDs[unitIdx] = textureID; |
| 3134 } | 3143 } |
| 3135 | 3144 |
| 3136 ResetTimestamp timestamp; | 3145 ResetTimestamp timestamp; |
| 3137 const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(&ti mestamp); | 3146 const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(&ti mestamp); |
| 3138 bool setAll = timestamp < this->getResetTimestamp(); | 3147 bool setAll = timestamp < this->getResetTimestamp(); |
| 3139 GrGLTexture::TexParams newTexParams; | 3148 GrGLTexture::TexParams newTexParams; |
| 3140 | 3149 |
| 3141 if (this->caps()->srgbSupport()) { | |
| 3142 // By default, the decision to allow SRGB decode is based on the destina tion config. | |
| 3143 // A texture can override that by specifying a value in GrTextureParams. | |
| 3144 newTexParams.fSRGBDecode = allowSRGBInputs ? GR_GL_DECODE_EXT : GR_GL_SK IP_DECODE_EXT; | |
| 3145 | |
| 3146 if (setAll || newTexParams.fSRGBDecode != oldTexParams.fSRGBDecode) { | |
| 3147 this->setTextureUnit(unitIdx); | |
| 3148 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, newTexP arams.fSRGBDecode)); | |
| 3149 } | |
| 3150 } | |
| 3151 | |
| 3152 static GrGLenum glMinFilterModes[] = { | 3150 static GrGLenum glMinFilterModes[] = { |
| 3153 GR_GL_NEAREST, | 3151 GR_GL_NEAREST, |
| 3154 GR_GL_LINEAR, | 3152 GR_GL_LINEAR, |
| 3155 GR_GL_LINEAR_MIPMAP_LINEAR | 3153 GR_GL_LINEAR_MIPMAP_LINEAR |
| 3156 }; | 3154 }; |
| 3157 static GrGLenum glMagFilterModes[] = { | 3155 static GrGLenum glMagFilterModes[] = { |
| 3158 GR_GL_NEAREST, | 3156 GR_GL_NEAREST, |
| 3159 GR_GL_LINEAR, | 3157 GR_GL_LINEAR, |
| 3160 GR_GL_LINEAR | 3158 GR_GL_LINEAR |
| 3161 }; | 3159 }; |
| 3162 GrTextureParams::FilterMode filterMode = params.filterMode(); | 3160 GrTextureParams::FilterMode filterMode = params.filterMode(); |
| 3163 | 3161 |
| 3164 if (GrTextureParams::kMipMap_FilterMode == filterMode) { | 3162 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
| 3165 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture- >config())) { | 3163 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture- >config())) { |
| 3166 filterMode = GrTextureParams::kBilerp_FilterMode; | 3164 filterMode = GrTextureParams::kBilerp_FilterMode; |
| 3167 } | 3165 } |
| 3168 } | 3166 } |
| 3169 | 3167 |
| 3170 newTexParams.fMinFilter = glMinFilterModes[filterMode]; | 3168 newTexParams.fMinFilter = glMinFilterModes[filterMode]; |
| 3171 newTexParams.fMagFilter = glMagFilterModes[filterMode]; | 3169 newTexParams.fMagFilter = glMagFilterModes[filterMode]; |
| 3172 | 3170 |
| 3171 bool enableSRGBDecode = false; | |
| 3172 if (GrPixelConfigIsSRGB(texture->config())) { | |
| 3173 enableSRGBDecode = allowSRGBInputs; | |
| 3174 | |
| 3175 newTexParams.fSRGBDecode = enableSRGBDecode ? GR_GL_DECODE_EXT : GR_GL_S KIP_DECODE_EXT; | |
| 3176 if (setAll || newTexParams.fSRGBDecode != oldTexParams.fSRGBDecode) { | |
| 3177 this->setTextureUnit(unitIdx); | |
| 3178 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, newTexP arams.fSRGBDecode)); | |
| 3179 } | |
| 3180 | |
| 3181 // If we're going to be using MipMaps, and they were last built with sRG B decode in the | |
| 3182 // wrong state, then mark them as dirty so we will re-run GenerateMipmap below... | |
| 3183 // TODO: Remove this code, shouldn't be necessary. | |
| 3184 if (GrTextureParams::kMipMap_FilterMode == filterMode && | |
| 3185 texture->texturePriv().mipMapsAreSRGBCorrect() != enableSRGBDecode) { | |
| 3186 texture->texturePriv().dirtyMipMaps(true); | |
| 3187 } | |
| 3188 } | |
| 3189 | |
| 3173 if (GrTextureParams::kMipMap_FilterMode == filterMode) { | 3190 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
| 3174 if (texture->texturePriv().mipMapsAreDirty()) { | 3191 if (texture->texturePriv().mipMapsAreDirty()) { |
| 3192 SkDebugf("Mip maps are dirty in bindTexture. Shouldn't happen.\n"); | |
| 3175 this->setTextureUnit(unitIdx); | 3193 this->setTextureUnit(unitIdx); |
| 3176 GL_CALL(GenerateMipmap(target)); | 3194 GL_CALL(GenerateMipmap(target)); |
| 3177 texture->texturePriv().dirtyMipMaps(false); | 3195 texture->texturePriv().dirtyMipMaps(false, enableSRGBDecode); |
| 3178 texture->texturePriv().setMaxMipMapLevel(SkMipMap::ComputeLevelCount ( | 3196 texture->texturePriv().setMaxMipMapLevel(SkMipMap::ComputeLevelCount ( |
| 3179 texture->width(), texture->height())); | 3197 texture->width(), texture->height())); |
| 3180 } | 3198 } |
| 3181 } | 3199 } |
| 3182 | 3200 |
| 3183 newTexParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel(); | 3201 newTexParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel(); |
| 3184 | 3202 |
| 3185 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); | 3203 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); |
| 3186 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); | 3204 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); |
| 3187 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz leRGBA); | 3205 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz leRGBA); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3271 get_tex_param_swizzle(texelConfig, this->glCaps(), glSwizzle); | 3289 get_tex_param_swizzle(texelConfig, this->glCaps(), glSwizzle); |
| 3272 this->setTextureSwizzle(unitIdx, GR_GL_TEXTURE_BUFFER, glSwizzle); | 3290 this->setTextureSwizzle(unitIdx, GR_GL_TEXTURE_BUFFER, glSwizzle); |
| 3273 buffTex.fSwizzle = this->glCaps().configSwizzle(texelConfig); | 3291 buffTex.fSwizzle = this->glCaps().configSwizzle(texelConfig); |
| 3274 } | 3292 } |
| 3275 | 3293 |
| 3276 buffer->setHasAttachedToTexture(); | 3294 buffer->setHasAttachedToTexture(); |
| 3277 fHWMaxUsedBufferTextureUnit = SkTMax(unitIdx, fHWMaxUsedBufferTextureUni t); | 3295 fHWMaxUsedBufferTextureUnit = SkTMax(unitIdx, fHWMaxUsedBufferTextureUni t); |
| 3278 } | 3296 } |
| 3279 } | 3297 } |
| 3280 | 3298 |
| 3299 void GrGLGpu::generateMipmaps(const GrTextureParams& params, bool allowSRGBInput s, | |
| 3300 GrGLTexture* texture) { | |
| 3301 SkASSERT(texture); | |
| 3302 | |
| 3303 // First, figure out if we need mips for this texture at all: | |
| 3304 GrTextureParams::FilterMode filterMode = params.filterMode(); | |
| 3305 | |
| 3306 if (GrTextureParams::kMipMap_FilterMode == filterMode) { | |
| 3307 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture- >config())) { | |
| 3308 filterMode = GrTextureParams::kBilerp_FilterMode; | |
| 3309 } | |
| 3310 } | |
| 3311 | |
| 3312 if (GrTextureParams::kMipMap_FilterMode != filterMode) { | |
| 3313 return; | |
| 3314 } | |
| 3315 | |
| 3316 // If this is an sRGB texture and the mips were previously built the "other" way | |
| 3317 // (gamma-correct vs. not), then we need to rebuild them. We don't need to c heck for | |
| 3318 // srgbSupport - we'll *never* get an sRGB pixel config if we don't support it. | |
| 3319 if (GrPixelConfigIsSRGB(texture->config()) && | |
| 3320 allowSRGBInputs != texture->texturePriv().mipMapsAreSRGBCorrect()) { | |
| 3321 texture->texturePriv().dirtyMipMaps(true); | |
| 3322 } | |
| 3323 | |
| 3324 // If the mips aren't dirty, we're done: | |
| 3325 if (!texture->texturePriv().mipMapsAreDirty()) { | |
| 3326 return; | |
| 3327 } | |
| 3328 | |
| 3329 // If we created a rt/tex and rendered to it without using a texture and now we're texturing | |
| 3330 // from the rt it will still be the last bound texture, but it needs resolvi ng. | |
| 3331 GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTa rget()); | |
| 3332 if (texRT) { | |
| 3333 this->onResolveRenderTarget(texRT); | |
| 3334 } | |
| 3335 | |
| 3336 GrGLenum target = texture->target(); | |
| 3337 this->setScratchTextureUnit(); | |
| 3338 GL_CALL(BindTexture(target, texture->textureID())); | |
| 3339 | |
| 3340 // Configure sRGB decode, if necessary. This state is the only thing needed for the driver | |
| 3341 // call (glGenerateMipmap) to work correctly. Our manual method dirties othe r state, too. | |
| 3342 if (GrPixelConfigIsSRGB(texture->config())) { | |
| 3343 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, | |
| 3344 allowSRGBInputs ? GR_GL_DECODE_EXT : GR_GL_SKIP_DE CODE_EXT)); | |
| 3345 } | |
| 3346 | |
| 3347 // Either do manual mipmap generation or (if that fails), just rely on the d river: | |
| 3348 if (!this->generateMipmap(texture, allowSRGBInputs)) { | |
| 3349 GL_CALL(GenerateMipmap(target)); | |
| 3350 } | |
| 3351 | |
| 3352 texture->texturePriv().dirtyMipMaps(false, allowSRGBInputs); | |
| 3353 texture->texturePriv().setMaxMipMapLevel(SkMipMap::ComputeLevelCount( | |
| 3354 texture->width(), texture->height())); | |
| 3355 | |
| 3356 // We have potentially set lots of state on the texture. Easiest to dirty it all: | |
| 3357 texture->textureParamsModified(); | |
| 3358 } | |
| 3359 | |
| 3281 void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swi zzle[]) { | 3360 void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swi zzle[]) { |
| 3282 this->setTextureUnit(unitIdx); | 3361 this->setTextureUnit(unitIdx); |
| 3283 if (this->glStandard() == kGLES_GrGLStandard) { | 3362 if (this->glStandard() == kGLES_GrGLStandard) { |
| 3284 // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA. | 3363 // ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA. |
| 3285 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0])); | 3364 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0])); |
| 3286 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1])); | 3365 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1])); |
| 3287 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2])); | 3366 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2])); |
| 3288 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3])); | 3367 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3])); |
| 3289 } else { | 3368 } else { |
| 3290 GR_STATIC_ASSERT(sizeof(swizzle[0]) == sizeof(GrGLint)); | 3369 GR_STATIC_ASSERT(sizeof(swizzle[0]) == sizeof(GrGLint)); |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4061 dstGLRect.fBottom, | 4140 dstGLRect.fBottom, |
| 4062 dstGLRect.fLeft + dstGLRect.fWidth, | 4141 dstGLRect.fLeft + dstGLRect.fWidth, |
| 4063 dstGLRect.fBottom + dstGLRect.fHeight, | 4142 dstGLRect.fBottom + dstGLRect.fHeight, |
| 4064 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); | 4143 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); |
| 4065 this->unbindTextureFBOForCopy(GR_GL_DRAW_FRAMEBUFFER, dst); | 4144 this->unbindTextureFBOForCopy(GR_GL_DRAW_FRAMEBUFFER, dst); |
| 4066 this->unbindTextureFBOForCopy(GR_GL_READ_FRAMEBUFFER, src); | 4145 this->unbindTextureFBOForCopy(GR_GL_READ_FRAMEBUFFER, src); |
| 4067 this->didWriteToSurface(dst, &dstRect); | 4146 this->didWriteToSurface(dst, &dstRect); |
| 4068 return true; | 4147 return true; |
| 4069 } | 4148 } |
| 4070 | 4149 |
| 4150 bool gManualMipmaps = true; | |
| 4151 | |
| 4152 // Manual implementation of glGenerateMipmap, to work around driver bugs w/sRGB | |
| 4153 // Uses glBlitFramebuffer to do a series of downsample operations to successive mips. | |
| 4154 bool GrGLGpu::generateMipmap(GrGLTexture* texture, bool gammaCorrect) { | |
| 4155 // Global switch for manual mipmap generation: | |
| 4156 if (!gManualMipmaps) { | |
| 4157 return false; | |
| 4158 } | |
| 4159 | |
| 4160 // We only handle 2D textures for now: | |
| 4161 if (GR_GL_TEXTURE_2D != texture->target()) { | |
| 4162 return false; | |
| 4163 } | |
| 4164 | |
| 4165 // Our iterative downsample requires the ability to limit which level we're sampling: | |
| 4166 if (!this->glCaps().mipMapLevelAndLodControlSupport()) { | |
| 4167 return false; | |
| 4168 } | |
| 4169 | |
| 4170 // Get and bind program: | |
| 4171 int progIdx = TextureTargetToCopyProgramIdx(texture->target()); | |
| 4172 if (!fCopyPrograms[progIdx].fProgram) { | |
| 4173 if (!this->createCopyProgram(progIdx)) { | |
| 4174 SkDebugf("Failed to create copy program.\n"); | |
| 4175 return false; | |
| 4176 } | |
| 4177 } | |
| 4178 GL_CALL(UseProgram(fCopyPrograms[progIdx].fProgram)); | |
| 4179 fHWProgramID = fCopyPrograms[progIdx].fProgram; | |
| 4180 | |
| 4181 int width = texture->width(); | |
| 4182 int height = texture->height(); | |
| 4183 int levelCount = SkMipMap::ComputeLevelCount(width, height) + 1; | |
| 4184 | |
| 4185 // Define all mips, if we haven't previously done so: | |
| 4186 if (0 == texture->texturePriv().maxMipMapLevel()) { | |
| 4187 GrGLenum internalFormat; | |
| 4188 GrGLenum externalFormat; | |
| 4189 GrGLenum externalType; | |
| 4190 if (!this->glCaps().getTexImageFormats(texture->desc().fConfig, texture- >desc().fConfig, | |
| 4191 &internalFormat, &externalFormat, &externalType)) { | |
| 4192 return false; | |
| 4193 } | |
| 4194 | |
| 4195 for (GrGLint level = 1; level < levelCount; ++level) { | |
| 4196 // Define the next mip: | |
| 4197 width = SkTMax(1, width / 2); | |
| 4198 height = SkTMax(1, height / 2); | |
| 4199 GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D, leve l, internalFormat, | |
| 4200 width, height, 0, | |
| 4201 externalFormat, extern alType, nullptr)); | |
| 4202 } | |
| 4203 } | |
| 4204 | |
| 4205 // Create (if necessary), then bind temporary FBO: | |
| 4206 if (0 == fTempDstFBOID) { | |
| 4207 GL_CALL(GenFramebuffers(1, &fTempDstFBOID)); | |
| 4208 } | |
| 4209 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fTempDstFBOID)); | |
| 4210 fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; | |
| 4211 | |
| 4212 // Turn FB sRGB on or off: | |
| 4213 this->setFramebufferSRGB(gammaCorrect); | |
| 4214 | |
| 4215 // Bind the texture, to get things basically configured. We'll be mucking wi th state further. | |
| 4216 this->setTextureUnit(0); | |
| 4217 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_F ilterMode); | |
| 4218 this->bindTexture(0, params, gammaCorrect, texture); | |
| 4219 | |
| 4220 // Vertex data: | |
| 4221 fHWVertexArrayState.setVertexArrayID(this, 0); | |
| 4222 | |
| 4223 GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray( this); | |
| 4224 attribs->set(this, 0, fCopyProgramArrayBuffer, kVec2f_GrVertexAttribType, 2 * sizeof(GrGLfloat), | |
| 4225 0); | |
| 4226 attribs->disableUnusedArrays(this, 0x1); | |
| 4227 | |
| 4228 // Set "simple" state once: | |
| 4229 GrXferProcessor::BlendInfo blendInfo; | |
| 4230 blendInfo.reset(); | |
| 4231 this->flushBlend(blendInfo, GrSwizzle::RGBA()); | |
| 4232 this->flushColorWrite(true); | |
| 4233 this->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace); | |
| 4234 this->flushHWAAState(nullptr, false, false); | |
| 4235 this->disableScissor(); | |
| 4236 GrStencilSettings stencil; | |
| 4237 stencil.setDisabled(); | |
| 4238 this->flushStencil(stencil); | |
| 4239 | |
| 4240 // Configure rects to always map entire previous mip to next mip: | |
| 4241 GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, 2.0f, 2.0f, -1.0f , -1.0f)); | |
| 4242 GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform, 1.0f, 1.0f, 0.0f, 0.0f)); | |
| 4243 GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0)); | |
| 4244 | |
| 4245 // Do all the blits: | |
| 4246 width = texture->width(); | |
| 4247 height = texture->height(); | |
| 4248 GrGLIRect viewport; | |
| 4249 viewport.fLeft = 0; | |
| 4250 viewport.fBottom = 0; | |
| 4251 for (GrGLint level = 1; level < levelCount; ++level) { | |
| 4252 // Only sample from previous mip | |
| 4253 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BASE_LEVEL, level - 1)); | |
| 4254 | |
| 4255 GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, | |
| 4256 GR_GL_TEXTURE_2D, texture->textureID(), lev el)); | |
| 4257 | |
| 4258 width = SkTMax(1, width / 2); | |
| 4259 height = SkTMax(1, height / 2); | |
| 4260 viewport.fWidth = width; | |
| 4261 viewport.fHeight = height; | |
| 4262 this->flushViewport(viewport); | |
| 4263 | |
| 4264 GrGLenum status; | |
| 4265 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); | |
| 4266 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { | |
| 4267 SkDebugf("FB status: 0x%08x\n", status); | |
| 4268 } | |
| 4269 | |
| 4270 GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4)); | |
| 4271 } | |
| 4272 | |
| 4273 // Unbind: | |
| 4274 GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, | |
| 4275 GR_GL_TEXTURE_2D, 0, 0)); | |
| 4276 this->didWriteToSurface(texture, nullptr, levelCount); | |
| 4277 | |
| 4278 return true; | |
| 4279 } | |
| 4280 | |
| 4071 void GrGLGpu::onGetMultisampleSpecs(GrRenderTarget* rt, | 4281 void GrGLGpu::onGetMultisampleSpecs(GrRenderTarget* rt, |
| 4072 const GrStencilSettings& stencil, | 4282 const GrStencilSettings& stencil, |
| 4073 int* effectiveSampleCnt, | 4283 int* effectiveSampleCnt, |
| 4074 SkAutoTDeleteArray<SkPoint>* sampleLocations ) { | 4284 SkAutoTDeleteArray<SkPoint>* sampleLocations ) { |
| 4075 SkASSERT(!rt->hasMixedSamples() || rt->renderTargetPriv().getStencilAttachme nt() || | 4285 SkASSERT(!rt->hasMixedSamples() || rt->renderTargetPriv().getStencilAttachme nt() || |
| 4076 stencil.isDisabled()); | 4286 stencil.isDisabled()); |
| 4077 | 4287 |
| 4078 this->flushStencil(stencil); | 4288 this->flushStencil(stencil); |
| 4079 this->flushHWAAState(rt, true, !stencil.isDisabled()); | 4289 this->flushHWAAState(rt, true, !stencil.isDisabled()); |
| 4080 this->flushRenderTarget(static_cast<GrGLRenderTarget*>(rt), &SkIRect::EmptyI Rect()); | 4290 this->flushRenderTarget(static_cast<GrGLRenderTarget*>(rt), &SkIRect::EmptyI Rect()); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4245 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() || | 4455 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() || |
| 4246 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) { | 4456 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) { |
| 4247 copyParams->fFilter = GrTextureParams::kNone_FilterMode; | 4457 copyParams->fFilter = GrTextureParams::kNone_FilterMode; |
| 4248 copyParams->fWidth = texture->width(); | 4458 copyParams->fWidth = texture->width(); |
| 4249 copyParams->fHeight = texture->height(); | 4459 copyParams->fHeight = texture->height(); |
| 4250 return true; | 4460 return true; |
| 4251 } | 4461 } |
| 4252 } | 4462 } |
| 4253 return false; | 4463 return false; |
| 4254 } | 4464 } |
| OLD | NEW |