void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { fCurrDrawState.fSrcBlend = srcCoeff; fCurrDrawState.fDstBlend = dstCoeff; #if GR_DEBUG switch (dstCoeff) { case kDC_BlendCoeff: case kIDC_BlendCoeff: case kDA_BlendCoeff: case kIDA_BlendCoeff: GrPrintf("Unexpected dst blend coeff. Won't work correctly with" "coverage stages.\n"); break; default: break; } switch (srcCoeff) { case kSC_BlendCoeff: case kISC_BlendCoeff: case kSA_BlendCoeff: case kISA_BlendCoeff: GrPrintf("Unexpected src blend coeff. Won't work correctly with" "coverage stages.\n"); break; default: break; } #endif }
GrGLuint GrGLProgram::CompileShader(GrGLenum type, int stringCnt, const char** strings, int* stringLengths) { GrGLuint shader = GR_GL(CreateShader(type)); if (0 == shader) { return 0; } GrGLint compiled = GR_GL_INIT_ZERO; GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths)); GR_GL(CompileShader(shader)); GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen)); GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get())); for (int i = 0; i < stringCnt; ++i) { if (NULL == stringLengths || stringLengths[i] < 0) { GrPrintf(strings[i]); } else { GrPrintf("%.*s", stringLengths[i], strings[i]); } } GrPrintf("\n%s", log.get()); } GrAssert(!"Shader compilation failed!"); GR_GL(DeleteShader(shader)); return 0; } return shader; }
void GrGLCaps::print() const { for (int i = 0; i < fStencilFormats.count(); ++i) { GrPrintf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n", i, fStencilFormats[i].fStencilBits, fStencilFormats[i].fTotalBits); } GR_STATIC_ASSERT(0 == kNone_MSFBOType); GR_STATIC_ASSERT(1 == kDesktopARB_MSFBOType); GR_STATIC_ASSERT(2 == kDesktopEXT_MSFBOType); GR_STATIC_ASSERT(3 == kAppleES_MSFBOType); static const char* gMSFBOExtStr[] = { "None", "ARB", "EXT", "Apple", }; GrPrintf("MSAA Type: %s\n", gMSFBOExtStr[fMSFBOType]); GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors); GrPrintf("Support RGBA8 Render Buffer: %s\n", (fRGBA8RenderbufferSupport ? "YES": "NO")); GrPrintf("BGRA is an internal format: %s\n", (fBGRAIsInternalFormat ? "YES": "NO")); GrPrintf("Support texture swizzle: %s\n", (fTextureSwizzleSupport ? "YES": "NO")); GrPrintf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO")); GrPrintf("Unpack Flip Y support: %s\n", (fUnpackFlipYSupport ? "YES": "NO")); GrPrintf("Pack Row length support: %s\n", (fPackRowLengthSupport ? "YES": "NO")); GrPrintf("Pack Flip Y support: %s\n", (fPackFlipYSupport ? "YES": "NO")); }
// Compiles a GL shader and attaches it to a program. Returns the shader ID if // successful, or 0 if not. static GrGLuint attach_shader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, const SkString& shaderSrc) { const GrGLInterface* gli = glCtx.interface(); GrGLuint shaderId; GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); if (0 == shaderId) { return 0; } const GrGLchar* sourceStr = shaderSrc.c_str(); GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); GR_GL_CALL(gli, CompileShader(shaderId)); // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. bool checkCompiled = !glCtx.isChromium(); #ifdef SK_DEBUG checkCompiled = true; #endif if (checkCompiled) { GrGLint compiled = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround bug in Chromium cmd // buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); GrPrintf(shaderSrc.c_str()); GrPrintf("\n%s", log.get()); } SkDEBUGFAIL("Shader compilation failed!"); GR_GL_CALL(gli, DeleteShader(shaderId)); return 0; } } TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); if (c_PrintShaders) { GrPrintf(shaderSrc.c_str()); GrPrintf("\n"); } // Attach the shader, but defer deletion until after we have linked the program. // This works around a bug in the Android emulator's GLES2 wrapper which // will immediately delete the shader object and free its memory even though it's // attached to a program, which then causes glLinkProgram to fail. GR_GL_CALL(gli, AttachShader(programId, shaderId)); return shaderId; }
// Compiles a GL shader, attaches it to a program, and releases the shader's reference. // (That way there's no need to hang on to the GL shader id and delete it later.) static bool attach_shader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, const SkString& shaderSrc) { const GrGLInterface* gli = glCtx.interface(); GrGLuint shaderId; GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); if (0 == shaderId) { return false; } const GrGLchar* sourceStr = shaderSrc.c_str(); GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); GR_GL_CALL(gli, CompileShader(shaderId)); // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. bool checkCompiled = !glCtx.info().isChromium(); #ifdef SK_DEBUG checkCompiled = true; #endif if (checkCompiled) { GrGLint compiled = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround bug in Chromium cmd // buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); GrPrintf(shaderSrc.c_str()); GrPrintf("\n%s", log.get()); } SkDEBUGFAIL("Shader compilation failed!"); GR_GL_CALL(gli, DeleteShader(shaderId)); return false; } } if (c_PrintShaders) { GrPrintf(shaderSrc.c_str()); GrPrintf("\n"); } GR_GL_CALL(gli, AttachShader(programId, shaderId)); GR_GL_CALL(gli, DeleteShader(shaderId)); return true; }
void GrGLCheckErr(const char* location, const char* call) { uint32_t err = GrGLGetGLInterface()->fGetError(); if (GR_GL_NO_ERROR != err) { GrPrintf("---- glGetError %x", err); if (NULL != location) { GrPrintf(" at\n\t%s", location); } if (NULL != call) { GrPrintf("\n\t\t%s", call); } GrPrintf("\n"); } }
void GrAARectRenderer::fillAARect(GrGpu* gpu, GrDrawTarget* target, const GrRect& devRect, bool useVertexCoverage) { GrVertexLayout layout = aa_rect_layout(useVertexCoverage); size_t vsize = GrDrawState::VertexSize(layout); GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu); if (NULL == indexBuffer) { GrPrintf("Failed to create index buffer!\n"); return; } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); set_inset_fan(fan0Pos, vsize, devRect, -SK_ScalarHalf, -SK_ScalarHalf); set_inset_fan(fan1Pos, vsize, devRect, SK_ScalarHalf, SK_ScalarHalf); verts += sizeof(GrPoint); for (int i = 0; i < 4; ++i) { *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; } GrColor innerColor; if (useVertexCoverage) { innerColor = 0xffffffff; } else { innerColor = target->getDrawState().getColor(); } verts += 4 * vsize; for (int i = 0; i < 4; ++i) { *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor; } target->setIndexSourceToBuffer(indexBuffer); target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, kVertsPerAAFillRect, kIndicesPerAAFillRect); }
void GrGLCheckErr(const GrGLInterface* gl, const char* location, const char* call) { uint32_t err = GR_GL_GET_ERROR(gl); if (GR_GL_NO_ERROR != err) { GrPrintf("---- glGetError 0x%x(%s)", err, get_error_string(err)); if (NULL != location) { GrPrintf(" at\n\t%s", location); } if (NULL != call) { GrPrintf("\n\t\t%s", call); } GrPrintf("\n"); } }
GrTexture* GrLockCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, const GrTextureParams* params) { GrTexture* result = NULL; if (!bitmap.isVolatile()) { // If the bitmap isn't changing try to find a cached copy first uint64_t key = bitmap.getGenerationID(); key |= ((uint64_t) bitmap.pixelRefOffset()) << 32; GrTextureDesc desc; desc.fWidth = bitmap.width(); desc.fHeight = bitmap.height(); desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); GrCacheData cacheData(key); result = ctx->findAndLockTexture(desc, cacheData, params); if (NULL == result) { result = sk_gr_create_bitmap_texture(ctx, key, params, bitmap); } } else { result = sk_gr_create_bitmap_texture(ctx, GrCacheData::kScratch_CacheID, params, bitmap); } if (NULL == result) { GrPrintf("---- failed to create texture for cache [%d %d]\n", bitmap.width(), bitmap.height()); } return result; }
GrGpu* GrGpu::Create(GrBackend backend, GrBackendContext backendContext, GrContext* context) { const GrGLInterface* glInterface = NULL; SkAutoTUnref<const GrGLInterface> glInterfaceUnref; if (kOpenGL_GrBackend == backend) { glInterface = reinterpret_cast<const GrGLInterface*>(backendContext); if (NULL == glInterface) { glInterface = GrGLDefaultInterface(); // By calling GrGLDefaultInterface we've taken a ref on the // returned object. We only want to hold that ref until after // the GrGpu is constructed and has taken ownership. glInterfaceUnref.reset(glInterface); } if (NULL == glInterface) { #ifdef SK_DEBUG GrPrintf("No GL interface provided!\n"); #endif return NULL; } GrGLContext ctx(glInterface); if (ctx.isInitialized()) { return SkNEW_ARGS(GrGpuGL, (ctx, context)); } } return NULL; }
bool GrGLShaderBuilder::finish() { SkASSERT(0 == fOutput.fProgramID); GL_CALL_RET(fOutput.fProgramID, CreateProgram()); if (!fOutput.fProgramID) { return false; } SkTDArray<GrGLuint> shadersToDelete; if (!this->compileAndAttachShaders(fOutput.fProgramID, &shadersToDelete)) { GL_CALL(DeleteProgram(fOutput.fProgramID)); return false; } this->bindProgramLocations(fOutput.fProgramID); if (fUniformManager->isUsingBindUniform()) { fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); } GL_CALL(LinkProgram(fOutput.fProgramID)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround // bug in chrome cmd buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GL_CALL(GetProgramInfoLog(fOutput.fProgramID, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } SkDEBUGFAIL("Error linking program"); GL_CALL(DeleteProgram(fOutput.fProgramID)); fOutput.fProgramID = 0; return false; } } if (!fUniformManager->isUsingBindUniform()) { fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); } for (int i = 0; i < shadersToDelete.count(); ++i) { GL_CALL(DeleteShader(shadersToDelete[i])); } return true; }
void GrResourceCache::addResource(const GrResourceKey& key, GrResource* resource, uint32_t ownershipFlags) { GrAssert(NULL == resource->getCacheEntry()); // we don't expect to create new resources during a purge. In theory // this could cause purgeAsNeeded() into an infinite loop (e.g. // each resource destroyed creates and locks 2 resources and // unlocks 1 thereby causing a new purge). GrAssert(!fPurging); GrAutoResourceCacheValidate atcv(this); GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource)); resource->setCacheEntry(entry); this->attachToHead(entry); fCache.insert(key, entry); #if GR_DUMP_TEXTURE_UPLOAD GrPrintf("--- add resource to cache %p, count=%d bytes= %d %d\n", entry, fEntryCount, resource->sizeInBytes(), fEntryBytes); #endif if (ownershipFlags & kHide_OwnershipFlag) { this->makeExclusive(entry); } }
GrTexture* GrLockAndRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, const GrTextureParams* params) { GrTexture* result = NULL; bool cache = !bitmap.isVolatile(); if (cache) { // If the bitmap isn't changing try to find a cached copy first. GrCacheID cacheID; generate_bitmap_cache_id(bitmap, &cacheID); GrTextureDesc desc; generate_bitmap_texture_desc(bitmap, &desc); result = ctx->findAndRefTexture(desc, cacheID, params); } if (NULL == result) { result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap); } if (NULL == result) { GrPrintf("---- failed to create texture for cache [%d %d]\n", bitmap.width(), bitmap.height()); } return result; }
void GrDrawTarget::onDrawRect(const SkRect& rect, const SkMatrix* matrix, const SkRect* localRect, const SkMatrix* localMatrix) { GrDrawState::AutoViewMatrixRestore avmr; if (NULL != matrix) { avmr.set(this->drawState(), *matrix); } set_vertex_attributes(this->drawState(), NULL != localRect); AutoReleaseGeometry geo(this, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } size_t vsize = this->drawState()->getVertexSize(); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); if (NULL != localRect) { SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + sizeof(SkPoint)); coords->setRectFan(localRect->fLeft, localRect->fTop, localRect->fRight, localRect->fBottom, vsize); if (NULL != localMatrix) { localMatrix->mapPointsWithStride(coords, vsize, 4); } } SkRect bounds; this->getDrawState().getViewMatrix().mapRect(&bounds, rect); this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds); }
void GrBitmapTextContext::flushGlyphs() { if (NULL == fDrawTarget) { return; } GrDrawState* drawState = fDrawTarget->drawState(); GrDrawState::AutoRestoreEffects are(drawState); drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); if (fCurrVertex > 0) { // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); SkASSERT(fCurrTexture); GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); // This effect could be stored with one of the cache objects (atlas?) drawState->addCoverageEffect( GrCustomCoordsTextureEffect::Create(fCurrTexture, params), kGlyphCoordsAttributeIndex)->unref(); if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) { drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(0xffffffff); } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || fPaint.numColorStages()) { GrPrintf("LCD Text will not draw correctly.\n"); } // We don't use the GrPaint's color in this case because it's been premultiplied by // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by // the mask texture color. The end result is that we get // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor int a = SkColorGetA(fSkPaint.getColor()); // paintAlpha drawState->setColor(SkColorSetARGB(a, a, a, a)); // paintColor drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); } else { // set back to normal in case we took LCD path previously. drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(fPaint.getColor()); } int nGlyphs = fCurrVertex / 4; fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, nGlyphs, 4, 6, &fVertexBounds); fDrawTarget->resetVertexSource(); fVertices = NULL; fMaxVertices = 0; fCurrVertex = 0; fVertexBounds.setLargestInverted(); SkSafeSetNull(fCurrTexture); } }
bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) { if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) { return true; } GrRenderTarget* rt = this->drawState()->getRenderTarget(); SkIRect copyRect; const GrClipData* clip = this->getClip(); clip->getConservativeBounds(rt, ©Rect); if (NULL != drawBounds) { SkIRect drawIBounds; drawBounds->roundOut(&drawIBounds); if (!copyRect.intersect(drawIBounds)) { #ifdef SK_DEBUG GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n"); #endif return false; } } else { #ifdef SK_DEBUG //GrPrintf("No dev bounds when dst copy is made.\n"); #endif } // MSAA consideration: When there is support for reading MSAA samples in the shader we could // have per-sample dst values by making the copy multisampled. GrTextureDesc desc; this->initCopySurfaceDstDesc(rt, &desc); desc.fWidth = copyRect.width(); desc.fHeight = copyRect.height(); GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch); if (NULL == ast.texture()) { GrPrintf("Failed to create temporary copy of destination texture.\n"); return false; } SkIPoint dstPoint = {0, 0}; if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) { dstCopy->setTexture(ast.texture()); dstCopy->setOffset(copyRect.fLeft, copyRect.fTop); return true; } else { return false; } }
GrAtlasMgr::~GrAtlasMgr() { SkSafeUnref(fTexture); SkDELETE_ARRAY(fPlotArray); fGpu->unref(); #if FONT_CACHE_STATS GrPrintf("Num uploads: %d\n", g_UploadCount); #endif }
void GrGLExtensions::print(const char* sep) const { if (NULL == sep) { sep = " "; } int cnt = fStrings->count(); for (int i = 0; i < cnt; ++i) { GrPrintf("%s%s", (*fStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); } }
GrAtlas::~GrAtlas() { fAtlasMgr->freePlot(fPlot.fX, fPlot.fY); delete fRects; #if GR_DEBUG --gCounter; GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter); #endif }
GrFontCache::~GrFontCache() { fCache.deleteAll(); for (int i = 0; i < kAtlasCount; ++i) { delete fAtlasMgr[i]; } fGpu->unref(); #if FONT_CACHE_STATS GrPrintf("Num purges: %d\n", g_PurgeCount); #endif }
/** * Destroying a resource may potentially trigger the unlock of additional * resources which in turn will trigger a nested purge. We block the nested * purge using the fPurging variable. However, the initial purge will keep * looping until either all resources in the cache are unlocked or we've met * the budget. There is an assertion in createAndLock to check against a * resource's destructor inserting new resources into the cache. If these * new resources were unlocked before purgeAsNeeded completed it could * potentially make purgeAsNeeded loop infinitely. */ void GrResourceCache::purgeAsNeeded() { if (!fPurging) { fPurging = true; bool withinBudget = false; bool changed = false; // The purging process is repeated several times since one pass // may free up other resources do { EntryList::Iter iter; changed = false; // Note: the following code relies on the fact that the // doubly linked list doesn't invalidate its data/pointers // outside of the specific area where a deletion occurs (e.g., // in internalDetach) GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart); while (NULL != entry) { GrAutoResourceCacheValidate atcv(this); if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { withinBudget = true; break; } GrResourceEntry* prev = iter.prev(); if (1 == entry->fResource->getRefCnt()) { changed = true; // remove from our cache fCache.remove(entry->key(), entry); // remove from our llist this->internalDetach(entry); #if GR_DUMP_TEXTURE_UPLOAD GrPrintf("--- ~resource from cache %p [%d %d]\n", entry->resource(), entry->resource()->width(), entry->resource()->height()); #endif delete entry; } entry = prev; } } while (!withinBudget && changed); fPurging = false; } }
GrAtlasMgr::~GrAtlasMgr() { for (size_t i = 0; i < GR_ARRAY_COUNT(fTexture); i++) { SkSafeUnref(fTexture[i]); } for (int i = 0; i < kCount_GrMaskFormats; ++i) { delete fPlotMgr[i]; } fGpu->unref(); #if FONT_CACHE_STATS GrPrintf("Num uploads: %d\n", g_UploadCount); #endif }
GrFontCache::~GrFontCache() { SkTDynamicHash<GrTextStrike, GrFontDescKey>::Iter iter(&fCache); while (!iter.done()) { SkDELETE(&(*iter)); ++iter; } for (int i = 0; i < kAtlasCount; ++i) { delete fAtlases[i]; } fGpu->unref(); #if FONT_CACHE_STATS GrPrintf("Num purges: %d\n", g_PurgeCount); #endif }
bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) { SK_TRACE_EVENT0("GrGLShaderBuilder::finish"); GrGLuint programId = 0; GL_CALL_RET(programId, CreateProgram()); if (!programId) { return false; } if (!this->compileAndAttachShaders(programId)) { GL_CALL(DeleteProgram(programId)); return false; } this->bindProgramLocations(programId); GL_CALL(LinkProgram(programId)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround // bug in chrome cmd buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GL_CALL(GetProgramInfoLog(programId, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } SkDEBUGFAIL("Error linking program"); GL_CALL(DeleteProgram(programId)); return false; } } fUniformManager.getUniformLocations(programId, fUniforms); *outProgramId = programId; return true; }
GrGpu* GrGpu::Create(GrEngine engine, GrPlatform3DContext context3D) { if (kOpenGL_Shaders_GrEngine == engine || kOpenGL_Fixed_GrEngine == engine) { // If no GL bindings have been installed, fall-back to calling the // GL functions that have been linked with the executable. if (!GrGLGetGLInterface()) { GrGLSetDefaultGLInterface(); // If there is no platform-default then just fail. if (!GrGLGetGLInterface()) { return NULL; } } if (!GrGLGetGLInterface()->validate(engine)) { #if GR_DEBUG GrPrintf("Failed GL interface validation!"); #endif return NULL; } } GrGpu* gpu = NULL; switch (engine) { case kOpenGL_Shaders_GrEngine: { #if 0 // old code path, will be removed soon gpu = new GrGpuGLShaders2; #else gpu = new GrGpuGLShaders(context3D); #endif } break; case kOpenGL_Fixed_GrEngine: gpu = new GrGpuGLFixed(context3D); break; case kDirect3D9_GrEngine: GrAssert(NULL != (void*)context3D); #if GR_WIN32_BUILD // gpu = new GrGpuD3D9((IDirect3DDevice9*)context3D); #endif break; default: GrAssert(!"unknown engine"); break; } return gpu; }
void GrGpu::printStats() const { if (GR_COLLECT_STATS) { GrPrintf( "-v-------------------------GPU STATS----------------------------v-\n" "Stats collection is: %s\n" "Draws: %04d, Verts: %04d, Indices: %04d\n" "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n" "TexCreates: %04d, RTCreates:%04d\n" "-^--------------------------------------------------------------^-\n", (GR_COLLECT_STATS ? "ON" : "OFF"), fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt, fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt, fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt); } }
GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) { fAtlasMgr = mgr; // just a pointer, not an owner fNext = NULL; fTexture = mgr->getTexture(format); // we're not an owner, just a pointer fPlot.set(plotX, plotY); fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER, GR_ATLAS_HEIGHT - BORDER); fMaskFormat = format; #if GR_DEBUG GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter); gCounter += 1; #endif }
bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath, const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { // generate verts using Android algorithm android::uirenderer::VertexBuffer vertices; android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL, &vertices); // set vertex layout depending on anti-alias GrVertexLayout layout = antiAlias ? GrDrawState::kCoverage_VertexLayoutBit : 0; // allocate our vert buffer int vertCount = vertices.getSize(); GrDrawTarget::AutoReleaseGeometry geo(target, layout, vertCount, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return false; } // copy android verts to our vertex buffer if (antiAlias) { ColorVertex* outVert = reinterpret_cast<ColorVertex*>(geo.vertices()); android::uirenderer::AlphaVertex* inVert = reinterpret_cast<android::uirenderer::AlphaVertex*>(vertices.getBuffer()); for (int i = 0; i < vertCount; ++i) { // copy vertex position outVert->pos.set(inVert->position[0], inVert->position[1]); // copy alpha int coverage = static_cast<int>(inVert->alpha * 0xff); outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage); ++outVert; ++inVert; } } else { size_t vsize = GrDrawState::VertexSize(layout); size_t copySize = vsize*vertCount; memcpy(geo.vertices(), vertices.getBuffer(), copySize); } // render it target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount); return true; }
void GrDrawTarget::drawRect(const GrRect& rect, const SkMatrix* matrix, const GrRect* srcRects[], const SkMatrix* srcMatrices[]) { GrVertexLayout layout = GetRectVertexLayout(srcRects); AutoReleaseGeometry geo(this, layout, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } SetRectVertices(rect, matrix, srcRects, srcMatrices, SK_ColorBLACK, layout, geo.vertices()); drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); }
void GrTextContext::flushGlyphs() { if (NULL == fDrawTarget) { return; } GrDrawState* drawState = fDrawTarget->drawState(); if (fCurrVertex > 0) { // setup our sampler state for our text texture/atlas drawState->stage(kGlyphMaskStage)->reset(); GrAssert(GrIsALIGN4(fCurrVertex)); GrAssert(fCurrTexture); GrTextureParams params(SkShader::kRepeat_TileMode, false); drawState->createTextureEffect(kGlyphMaskStage, fCurrTexture, SkMatrix::I(), params); if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || fPaint.hasColorStage()) { GrPrintf("LCD Text will not draw correctly.\n"); } // setup blend so that we get mask * paintColor + (1-mask)*dstColor drawState->setBlendConstant(fPaint.getColor()); drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); // don't modulate by the paint's color in the frag since we're // already doing it via the blend const. drawState->setColor(0xffffffff); } else { // set back to normal in case we took LCD path previously. drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(fPaint.getColor()); } int nGlyphs = fCurrVertex / 4; fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, nGlyphs, 4, 6); fDrawTarget->resetVertexSource(); fVertices = NULL; fMaxVertices = 0; fCurrVertex = 0; GrSafeSetNull(fCurrTexture); } drawState->disableStages(); fDrawTarget = NULL; }