diff options
Diffstat (limited to 'src/gl/SkGL.cpp')
-rw-r--r-- | src/gl/SkGL.cpp | 526 |
1 files changed, 0 insertions, 526 deletions
diff --git a/src/gl/SkGL.cpp b/src/gl/SkGL.cpp deleted file mode 100644 index 1fce98f..0000000 --- a/src/gl/SkGL.cpp +++ /dev/null @@ -1,526 +0,0 @@ -#include "SkGL.h" -#include "SkColorPriv.h" -#include "SkGeometry.h" -#include "SkPaint.h" -#include "SkPath.h" -#include "SkTemplates.h" -#include "SkXfermode.h" - -//#define TRACE_TEXTURE_CREATION - -/////////////////////////////////////////////////////////////////////////////// - -#ifdef SK_GL_HAS_COLOR4UB -static inline void gl_pmcolor(U8CPU r, U8CPU g, U8CPU b, U8CPU a) { - glColor4ub(r, g, b, a); -} - -void SkGL::SetAlpha(U8CPU alpha) { - glColor4ub(alpha, alpha, alpha, alpha); -} -#else -static inline SkFixed byte2fixed(U8CPU value) { - return (value + (value >> 7)) << 8; -} - -static inline void gl_pmcolor(U8CPU r, U8CPU g, U8CPU b, U8CPU a) { - glColor4x(byte2fixed(r), byte2fixed(g), byte2fixed(b), byte2fixed(a)); -} - -void SkGL::SetAlpha(U8CPU alpha) { - SkFixed fa = byte2fixed(alpha); - glColor4x(fa, fa, fa, fa); -} -#endif - -void SkGL::SetColor(SkColor c) { - SkPMColor pm = SkPreMultiplyColor(c); - gl_pmcolor(SkGetPackedR32(pm), - SkGetPackedG32(pm), - SkGetPackedB32(pm), - SkGetPackedA32(pm)); -} - -static const GLenum gXfermodeCoeff2Blend[] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, -}; - -void SkGL::SetPaint(const SkPaint& paint, bool isPremul, bool justAlpha) { - if (justAlpha) { - SkGL::SetAlpha(paint.getAlpha()); - } else { - SkGL::SetColor(paint.getColor()); - } - - GLenum sm = GL_ONE; - GLenum dm = GL_ONE_MINUS_SRC_ALPHA; - - SkXfermode* mode = paint.getXfermode(); - SkXfermode::Coeff sc, dc; - if (mode && mode->asCoeff(&sc, &dc)) { - sm = gXfermodeCoeff2Blend[sc]; - dm = gXfermodeCoeff2Blend[dc]; - } - - // hack for text, which is not-premul (afaik) - if (!isPremul) { - if (GL_ONE == sm) { - sm = GL_SRC_ALPHA; - } - } - - glEnable(GL_BLEND); - glBlendFunc(sm, dm); - - if (paint.isDither()) { - glEnable(GL_DITHER); - } else { - glDisable(GL_DITHER); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkGL::DumpError(const char caller[]) { - GLenum err = glGetError(); - if (err) { - SkDebugf("---- glGetError(%s) %d\n", caller, err); - } -} - -void SkGL::SetRGBA(uint8_t rgba[], const SkColor src[], int count) { - for (int i = 0; i < count; i++) { - SkPMColor c = SkPreMultiplyColor(*src++); - *rgba++ = SkGetPackedR32(c); - *rgba++ = SkGetPackedG32(c); - *rgba++ = SkGetPackedB32(c); - *rgba++ = SkGetPackedA32(c); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkGL::Scissor(const SkIRect& r, int viewportHeight) { - glScissor(r.fLeft, viewportHeight - r.fBottom, r.width(), r.height()); -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkGL::Ortho(float left, float right, float bottom, float top, - float near, float far) { - - float mat[16]; - - sk_bzero(mat, sizeof(mat)); - - mat[0] = 2 / (right - left); - mat[5] = 2 / (top - bottom); - mat[10] = 2 / (near - far); - mat[15] = 1; - - mat[12] = (right + left) / (left - right); - mat[13] = (top + bottom) / (bottom - top); - mat[14] = (far + near) / (near - far); - - glMultMatrixf(mat); -} - -/////////////////////////////////////////////////////////////////////////////// - -static bool canBeTexture(const SkBitmap& bm, GLenum* format, GLenum* type) { - switch (bm.config()) { - case SkBitmap::kARGB_8888_Config: - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; - break; - case SkBitmap::kRGB_565_Config: - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - break; - case SkBitmap::kARGB_4444_Config: - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_4_4_4_4; - break; - case SkBitmap::kIndex8_Config: -#ifdef SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D - *format = GL_PALETTE8_RGBA8_OES; - *type = GL_UNSIGNED_BYTE; // unused I think -#else - // we promote index to argb32 - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; -#endif - break; - case SkBitmap::kA8_Config: - *format = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; - break; - default: - return false; - } - return true; -} - -#define SK_GL_SIZE_OF_PALETTE (256 * sizeof(SkPMColor)) - -size_t SkGL::ComputeTextureMemorySize(const SkBitmap& bitmap) { - int shift = 0; - size_t adder = 0; - switch (bitmap.config()) { - case SkBitmap::kARGB_8888_Config: - case SkBitmap::kRGB_565_Config: - case SkBitmap::kARGB_4444_Config: - case SkBitmap::kA8_Config: - // we're good as is - break; - case SkBitmap::kIndex8_Config: -#ifdef SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D - // account for the colortable - adder = SK_GL_SIZE_OF_PALETTE; -#else - // we promote index to argb32 - shift = 2; -#endif - break; - default: - return 0; - } - return (bitmap.getSize() << shift) + adder; -} - -#ifdef SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D -/* Fill out buffer with the compressed format GL expects from a colortable - based bitmap. [palette (colortable) + indices]. - - At the moment I always take the 8bit version, since that's what my data - is. I could detect that the colortable.count is <= 16, and then repack the - indices as nibbles to save RAM, but it would take more time (i.e. a lot - slower than memcpy), so I'm skipping that for now. - - GL wants a full 256 palette entry, even though my ctable is only as big - as the colortable.count says it is. I presume it is OK to leave any - trailing entries uninitialized, since none of my indices should exceed - ctable->count(). -*/ -static void build_compressed_data(void* buffer, const SkBitmap& bitmap) { - SkASSERT(SkBitmap::kIndex8_Config == bitmap.config()); - - SkColorTable* ctable = bitmap.getColorTable(); - uint8_t* dst = (uint8_t*)buffer; - - memcpy(dst, ctable->lockColors(), ctable->count() * sizeof(SkPMColor)); - ctable->unlockColors(false); - - // always skip a full 256 number of entries, even if we memcpy'd fewer - dst += SK_GL_SIZE_OF_PALETTE; - memcpy(dst, bitmap.getPixels(), bitmap.getSize()); -} -#endif - -/* Return true if the bitmap cannot be supported in its current config as a - texture, and it needs to be promoted to ARGB32. - */ -static bool needToPromoteTo32bit(const SkBitmap& bitmap) { - if (bitmap.config() == SkBitmap::kIndex8_Config) { -#ifdef SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D - const int w = bitmap.width(); - const int h = bitmap.height(); - if (SkNextPow2(w) == w && SkNextPow2(h) == h) { - // we can handle Indx8 if we're a POW2 - return false; - } -#endif - return true; // must promote to ARGB32 - } - return false; -} - -GLuint SkGL::BindNewTexture(const SkBitmap& origBitmap, SkPoint* max) { - SkBitmap tmpBitmap; - const SkBitmap* bitmap = &origBitmap; - - if (needToPromoteTo32bit(origBitmap)) { - origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config); - // now bitmap points to our temp, which has been promoted to 32bits - bitmap = &tmpBitmap; - } - - GLenum format, type; - if (!canBeTexture(*bitmap, &format, &type)) { - return 0; - } - - SkAutoLockPixels alp(*bitmap); - if (!bitmap->readyToDraw()) { - return 0; - } - - GLuint textureName; - glGenTextures(1, &textureName); - - glBindTexture(GL_TEXTURE_2D, textureName); - - // express rowbytes as a number of pixels for ow - int ow = bitmap->rowBytesAsPixels(); - int oh = bitmap->height(); - int nw = SkNextPow2(ow); - int nh = SkNextPow2(oh); - - glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); - - // check if we need to scale to create power-of-2 dimensions -#ifdef SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D - if (SkBitmap::kIndex8_Config == bitmap->config()) { - size_t imagesize = bitmap->getSize() + SK_GL_SIZE_OF_PALETTE; - SkAutoMalloc storage(imagesize); - - build_compressed_data(storage.get(), *bitmap); - // we only support POW2 here (GLES 1.0 restriction) - SkASSERT(ow == nw); - SkASSERT(oh == nh); - glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, ow, oh, 0, - imagesize, storage.get()); - } else // fall through to non-compressed logic -#endif - { - if (ow != nw || oh != nh) { - glTexImage2D(GL_TEXTURE_2D, 0, format, nw, nh, 0, - format, type, NULL); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ow, oh, - format, type, bitmap->getPixels()); - } else { - // easy case, the bitmap is already pow2 - glTexImage2D(GL_TEXTURE_2D, 0, format, ow, oh, 0, - format, type, bitmap->getPixels()); - } - } - -#ifdef TRACE_TEXTURE_CREATION - SkDebugf("--- new texture [%d] size=(%d %d) bpp=%d\n", textureName, ow, oh, - bitmap->bytesPerPixel()); -#endif - - if (max) { - max->fX = SkFixedToScalar(bitmap->width() << (16 - SkNextLog2(nw))); - max->fY = SkFixedToScalar(oh << (16 - SkNextLog2(nh))); - } - return textureName; -} - -static const GLenum gTileMode2GLWrap[] = { - GL_CLAMP_TO_EDGE, - GL_REPEAT, -#if GL_VERSION_ES_CM_1_0 - GL_REPEAT // GLES doesn't support MIRROR -#else - GL_MIRRORED_REPEAT -#endif -}; - -void SkGL::SetTexParams(bool doFilter, - SkShader::TileMode tx, SkShader::TileMode ty) { - SkASSERT((unsigned)tx < SK_ARRAY_COUNT(gTileMode2GLWrap)); - SkASSERT((unsigned)ty < SK_ARRAY_COUNT(gTileMode2GLWrap)); - - GLenum filter = doFilter ? GL_LINEAR : GL_NEAREST; - - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gTileMode2GLWrap[tx]); - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gTileMode2GLWrap[ty]); -} - -void SkGL::SetTexParamsClamp(bool doFilter) { - GLenum filter = doFilter ? GL_LINEAR : GL_NEAREST; - - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkGL::DrawVertices(int count, GLenum mode, - const SkGLVertex* SK_RESTRICT vertex, - const SkGLVertex* SK_RESTRICT texCoords, - const uint8_t* SK_RESTRICT colorArray, - const uint16_t* SK_RESTRICT indexArray, - SkGLClipIter* iter) { - SkASSERT(NULL != vertex); - - if (NULL != texCoords) { - glEnable(GL_TEXTURE_2D); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, SK_GLType, 0, texCoords); - } else { - glDisable(GL_TEXTURE_2D); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - - if (NULL != colorArray) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, colorArray); - glShadeModel(GL_SMOOTH); - } else { - glDisableClientState(GL_COLOR_ARRAY); - glShadeModel(GL_FLAT); - } - - glVertexPointer(2, SK_GLType, 0, vertex); - - if (NULL != indexArray) { - if (iter) { - while (!iter->done()) { - iter->scissor(); - glDrawElements(mode, count, GL_UNSIGNED_SHORT, indexArray); - iter->next(); - } - } else { - glDrawElements(mode, count, GL_UNSIGNED_SHORT, indexArray); - } - } else { - if (iter) { - while (!iter->done()) { - iter->scissor(); - glDrawArrays(mode, 0, count); - iter->next(); - } - } else { - glDrawArrays(mode, 0, count); - } - } -} - -void SkGL::PrepareForFillPath(SkPaint* paint) { - if (paint->getStrokeWidth() <= 0) { - paint->setStrokeWidth(SK_Scalar1); - } -} - -void SkGL::FillPath(const SkPath& path, const SkPaint& paint, bool useTex, - SkGLClipIter* iter) { - SkPaint p(paint); - SkPath fillPath; - - SkGL::PrepareForFillPath(&p); - p.getFillPath(path, &fillPath); - SkGL::DrawPath(fillPath, useTex, iter); -} - -// should return max of all contours, rather than the sum (to save temp RAM) -static int worst_case_edge_count(const SkPath& path) { - int edgeCount = 0; - - SkPath::Iter iter(path, true); - SkPath::Verb verb; - - while ((verb = iter.next(NULL)) != SkPath::kDone_Verb) { - switch (verb) { - case SkPath::kLine_Verb: - edgeCount += 1; - break; - case SkPath::kQuad_Verb: - edgeCount += 8; - break; - case SkPath::kCubic_Verb: - edgeCount += 16; - break; - default: - break; - } - } - return edgeCount; -} - -void SkGL::DrawPath(const SkPath& path, bool useTex, SkGLClipIter* clipIter) { - const SkRect& bounds = path.getBounds(); - if (bounds.isEmpty()) { - return; - } - - int maxPts = worst_case_edge_count(path); - // add 1 for center of fan, and 1 for closing edge - SkAutoSTMalloc<32, SkGLVertex> storage(maxPts + 2); - SkGLVertex* base = storage.get(); - SkGLVertex* vert = base; - SkGLVertex* texs = useTex ? base : NULL; - - SkPath::Iter pathIter(path, true); - SkPoint pts[4]; - - bool needEnd = false; - - for (;;) { - switch (pathIter.next(pts)) { - case SkPath::kMove_Verb: - if (needEnd) { - SkGL::DrawVertices(vert - base, GL_TRIANGLE_FAN, - base, texs, NULL, NULL, clipIter); - clipIter->safeRewind(); - vert = base; - } - needEnd = true; - // center of the FAN - vert->setScalars(bounds.centerX(), bounds.centerY()); - vert++; - // add first edge point - vert->setPoint(pts[0]); - vert++; - break; - case SkPath::kLine_Verb: - vert->setPoint(pts[1]); - vert++; - break; - case SkPath::kQuad_Verb: { - const int n = 8; - const SkScalar dt = SK_Scalar1 / n; - SkScalar t = dt; - for (int i = 1; i < n; i++) { - SkPoint loc; - SkEvalQuadAt(pts, t, &loc, NULL); - t += dt; - vert->setPoint(loc); - vert++; - } - vert->setPoint(pts[2]); - vert++; - break; - } - case SkPath::kCubic_Verb: { - const int n = 16; - const SkScalar dt = SK_Scalar1 / n; - SkScalar t = dt; - for (int i = 1; i < n; i++) { - SkPoint loc; - SkEvalCubicAt(pts, t, &loc, NULL, NULL); - t += dt; - vert->setPoint(loc); - vert++; - } - vert->setPoint(pts[3]); - vert++; - break; - } - case SkPath::kClose_Verb: - break; - case SkPath::kDone_Verb: - goto FINISHED; - } - } -FINISHED: - if (needEnd) { - SkGL::DrawVertices(vert - base, GL_TRIANGLE_FAN, base, texs, - NULL, NULL, clipIter); - } -} - |