SkGLDevice::TexCache* SkGLDevice::setupGLPaintShader(const SkPaint& paint) { SkGL::SetPaint(paint); SkShader* shader = paint.getShader(); if (NULL == shader) { return NULL; } if (!shader->setContext(this->accessBitmap(false), paint, this->matrix())) { return NULL; } SkBitmap bitmap; SkMatrix matrix; SkShader::TileMode tileModes[2]; if (!shader->asABitmap(&bitmap, &matrix, tileModes)) { return NULL; } bitmap.lockPixels(); if (!bitmap.readyToDraw()) { return NULL; } // see if we've already cached the bitmap from the shader SkPoint max; GLuint name; TexCache* cache = SkGLDevice::LockTexCache(bitmap, &name, &max); // the lock has already called glBindTexture for us SkGL::SetTexParams(paint.isFilterBitmap(), tileModes[0], tileModes[1]); // since our texture coords will be in local space, we wack the texture // matrix to map them back into 0...1 before we load it SkMatrix localM; if (shader->getLocalMatrix(&localM)) { SkMatrix inverse; if (localM.invert(&inverse)) { matrix.preConcat(inverse); } } matrix.postScale(max.fX / bitmap.width(), max.fY / bitmap.height()); glMatrixMode(GL_TEXTURE); SkGL::LoadMatrix(matrix); glMatrixMode(GL_MODELVIEW); // since we're going to use a shader/texture, we don't want the color, // just its alpha SkGL::SetAlpha(paint.getAlpha()); // report that we have setup the texture return cache; }
void SkGLDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) { if (false) { SkRect bounds; SkIRect ibounds; bounds.set(vertices, vertexCount); bounds.round(&ibounds); SkDebugf("---- drawverts: %d pts, texs=%d colors=%d indices=%d bounds [%d %d]\n", vertexCount, texs!=0, colors!=0, indexCount, ibounds.width(), ibounds.height()); } SkGLClipIter* iter = this->updateMatrixClip(); SkGL::SetPaint(paint); const SkGLVertex* glVerts; const SkGLVertex* glTexs = NULL; #if GLSCALAR_IS_SCALAR glVerts = (const SkGLVertex*)vertices; #else SkAutoSTMalloc<32, SkGLVertex> storage(vertexCount); storage.get()->setPoints(vertices, vertexCount); glVerts = storage.get(); #endif uint8_t* colorArray = NULL; if (colors) { colorArray = (uint8_t*)sk_malloc_throw(vertexCount*4); SkGL::SetRGBA(colorArray, colors, vertexCount); } SkAutoFree afca(colorArray); SkGLVertex* texArray = NULL; TexCache* cache = NULL; if (texs && paint.getShader()) { SkShader* shader = paint.getShader(); // if (!shader->setContext(this->accessBitmap(), paint, *draw.fMatrix)) { if (!shader->setContext(*draw.fBitmap, paint, *draw.fMatrix)) { goto DONE; } SkBitmap bitmap; SkMatrix matrix; SkShader::TileMode tileModes[2]; if (shader->asABitmap(&bitmap, &matrix, tileModes)) { SkPoint max; GLuint name; cache = SkGLDevice::LockTexCache(bitmap, &name, &max); if (NULL == cache) { return; } matrix.postScale(max.fX / bitmap.width(), max.fY / bitmap.height()); glMatrixMode(GL_TEXTURE); SkGL::LoadMatrix(matrix); glMatrixMode(GL_MODELVIEW); #if GLSCALAR_IS_SCALAR glTexs = (const SkGLVertex*)texs; #else texArray = (SkGLVertex*)sk_malloc_throw(vertexCount * sizeof(SkGLVertex)); texArray->setPoints(texs, vertexCount); glTexs = texArray; #endif SkGL::SetPaintAlpha(paint); SkGL::SetTexParams(paint.isFilterBitmap(), tileModes[0], tileModes[1]); } } DONE: SkAutoFree aftex(texArray); SkGL::DrawVertices(indices ? indexCount : vertexCount, gVertexModeToGL[vmode], glVerts, glTexs, colorArray, indices, iter); if (cache) { SkGLDevice::UnlockTexCache(cache); } }