ImageTexture::ImageTexture(SkBitmapRef* img) : m_imageRef(img) , m_image(0) , m_textureId(0) , m_refCount(0) { #ifdef DEBUG_COUNT ClassTracker::instance()->increment("ImageTexture"); #endif if (!m_imageRef) return; SkBitmap* bitmap = &m_imageRef->bitmap(); m_image = new SkBitmap(); int w = bitmap->width(); int h = bitmap->height(); m_image->setConfig(SkBitmap::kARGB_8888_Config, w, h); m_image->allocPixels(); SkDevice* device = new SkDevice(NULL, *m_image, false); SkCanvas canvas; canvas.setDevice(device); device->unref(); SkRect dest; dest.set(0, 0, w, h); m_image->setIsOpaque(false); m_image->eraseARGB(0, 0, 0, 0); canvas.drawBitmapRect(*bitmap, 0, dest); }
static void make_bitmap(SkBitmap* bitmap, GrContext* ctx) { SkCanvas canvas; if (ctx) { SkDevice* dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, 64, 64); canvas.setDevice(dev)->unref(); *bitmap = dev->accessBitmap(false); } else { bitmap->setConfig(SkBitmap::kARGB_8888_Config, 64, 64); bitmap->allocPixels(); canvas.setBitmapDevice(*bitmap); } canvas.drawColor(SK_ColorRED); SkPaint paint; paint.setAntiAlias(true); const SkPoint pts[] = { { 0, 0 }, { 64, 64 } }; const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE }; paint.setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode))->unref(); canvas.drawCircle(32, 32, 32, paint); }
TiledPipeController::TiledPipeController(const SkBitmap& bitmap, const SkMatrix* initial) : INHERITED(NULL) { int32_t top = 0; int32_t bottom; int32_t height = bitmap.height() / NumberOfTiles; SkIRect rect; for (int i = 0; i < NumberOfTiles; i++) { bottom = i + 1 == NumberOfTiles ? bitmap.height() : top + height; rect.setLTRB(0, top, bitmap.width(), bottom); top = bottom; bool extracted = bitmap.extractSubset(&fBitmaps[i], rect); SkASSERT(extracted); SkDevice* device = new SkDevice(fBitmaps[i]); SkCanvas* canvas = new SkCanvas(device); device->unref(); if (initial != NULL) { canvas->setMatrix(*initial); } canvas->translate(SkIntToScalar(-rect.left()), SkIntToScalar(-rect.top())); if (0 == i) { fReader.setCanvas(canvas); } else { fReaders[i - 1].setCanvas(canvas); } canvas->unref(); } }
~DeviceCM() { if (NULL != fDevice) { fDevice->unlockPixels(); fDevice->unref(); } SkDELETE(fPaint); }
static SkBitmap createBitmap(const SkPath& path) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, SkImageWidget::kImageWidgetWidth, SkImageWidget::kImageWidgetHeight); bitmap.allocPixels(); bitmap.eraseColor(SK_ColorWHITE); SkDevice* device = new SkDevice(bitmap); SkCanvas canvas(device); device->unref(); const SkRect& bounds = path.getBounds(); if (bounds.width() > bounds.height()) { canvas.scale(SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetWidth)/bounds.width()), SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetHeight)/bounds.width())); } else { canvas.scale(SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetWidth)/bounds.height()), SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetHeight)/bounds.height())); } canvas.translate(-bounds.fLeft+2, -bounds.fTop+2); SkPaint p; p.setColor(SK_ColorBLACK); p.setStyle(SkPaint::kStroke_Style); canvas.drawPath(path, p); return bitmap; }
static void _canvas_device_region(SkCanvas *canvas, SkRegion *region) { SkDevice *device; int w, h; device = canvas->getDevice(); w = device->width(); h = device->height(); region->setRect(0, 0, w, h); }
bool SkGpuCanvas::getViewport(SkIPoint* size) const { if (size) { SkDevice* device = this->getDevice(); if (device) { size->set(device->width(), device->height()); } else { size->set(0, 0); } } return true; }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); Vector<char> encodedImage, base64Data; SkDevice* device = context()->platformContext()->canvas()->getDevice(); if (!encodeImage(device->accessBitmap(false), mimeType, quality, &encodedImage)) return "data:,"; base64Encode(encodedImage, base64Data); return "data:" + mimeType + ";base64," + base64Data; }
/// M: added for HTML5-benchmark performance @{ PassRefPtr<Image> ImageBuffer::getContextImageRef() const { SkCanvas* canvas = imageBufferCanvas(this); if (!canvas) return 0; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmapRef* ref = new SkBitmapRef(orig); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* loc) { if (fCount < 1) { return false; } const SkIRect srcBounds = SkIRect::MakeXYWH(loc->x(), loc->y(), src.width(), src.height()); SkIRect bounds; if (!this->filterBounds(srcBounds, ctm, &bounds)) { return false; } const int x0 = bounds.left(); const int y0 = bounds.top(); SkDevice* dst = proxy->createDevice(bounds.width(), bounds.height()); if (NULL == dst) { return false; } OwnDeviceCanvas canvas(dst); SkPaint paint; for (int i = 0; i < fCount; ++i) { SkBitmap tmp; const SkBitmap* srcPtr; SkIPoint pos = *loc; SkImageFilter* filter = fFilters[i]; if (filter) { if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) { return false; } srcPtr = &tmp; } else { srcPtr = &src; } if (fModes) { paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); } else { paint.setXfermode(NULL); } canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint); } loc->set(bounds.left(), bounds.top()); *result = dst->accessBitmap(false); return true; }
bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& matrix, SkBitmap* result, SkIPoint*) { SkScalar scale = fScale; if (scale > SK_Scalar1 || scale <= 0) { return false; } int dstW = SkScalarRoundToInt(src.width() * scale); int dstH = SkScalarRoundToInt(src.height() * scale); if (dstW < 1) { dstW = 1; } if (dstH < 1) { dstH = 1; } SkBitmap tmp; // downsample { SkDevice* dev = proxy->createDevice(dstW, dstH); if (NULL == dev) { return false; } OwnDeviceCanvas canvas(dev); SkPaint paint; paint.setFilterBitmap(true); canvas.scale(scale, scale); canvas.drawBitmap(src, 0, 0, &paint); tmp = dev->accessBitmap(false); } // upscale { SkDevice* dev = proxy->createDevice(src.width(), src.height()); if (NULL == dev) { return false; } OwnDeviceCanvas canvas(dev); SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()), SkIntToScalar(src.height())); canvas.drawBitmapRect(tmp, NULL, r, NULL); *result = dev->accessBitmap(false); } return true; }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { SkDevice* device = context()->platformContext()->canvas()->getDevice(); SkBitmap bitmap = device->accessBitmap(false); // if we can't see the pixels directly, call readPixels() to get a copy. // this could happen if the device is backed by a GPU. bitmap.lockPixels(); // balanced by our destructor, or explicitly if getPixels() fails if (!bitmap.getPixels()) { bitmap.unlockPixels(); SkIRect bounds = SkIRect::MakeWH(device->width(), device->height()); if (!device->readPixels(bounds, &bitmap)) return "data:,"; } return ImageToDataURL(bitmap, mimeType, quality); }
PassRefPtr<Image> ImageBuffer::copyImage() const { ASSERT(context()); SkCanvas* canvas = imageBufferCanvas(this); if (!canvas) return 0; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmap copy; if (PlatformBridge::canSatisfyMemoryAllocation(orig.getSize())) orig.copyTo(©, orig.config()); SkBitmapRef* ref = new SkBitmapRef(copy); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip, const SkClipStack& clipStack, SkRegion* updateClip) { int x = fDevice->getOrigin().x(); int y = fDevice->getOrigin().y(); int width = fDevice->width(); int height = fDevice->height(); if ((x | y) == 0) { fMatrix = &totalMatrix; fClip = totalClip; } else { fMatrixStorage = totalMatrix; fMatrixStorage.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); fMatrix = &fMatrixStorage; totalClip.translate(-x, -y, &fClip); } fClip.op(0, 0, width, height, SkRegion::kIntersect_Op); // intersect clip, but don't translate it (yet) if (updateClip) { updateClip->op(x, y, x + width, y + height, SkRegion::kDifference_Op); } fDevice->setMatrixClip(*fMatrix, fClip, clipStack); #ifdef SK_DEBUG if (!fClip.isEmpty()) { SkIRect deviceR; deviceR.set(0, 0, width, height); SkASSERT(deviceR.contains(fClip.getBounds())); } #endif // default is to assume no external matrix fMVMatrix = NULL; fExtMatrix = NULL; }
static SkBitmap createBitmap(const SkBitmap& input, const SkRect* srcRect) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, SkImageWidget::kImageWidgetWidth, SkImageWidget::kImageWidgetHeight); bitmap.allocPixels(); bitmap.eraseColor(SK_ColorLTGRAY); SkDevice* device = new SkDevice(bitmap); SkCanvas canvas(device); device->unref(); SkScalar xScale = (SkImageWidget::kImageWidgetWidth-2.0) / input.width(); SkScalar yScale = (SkImageWidget::kImageWidgetHeight-2.0) / input.height(); if (input.width() > input.height()) { yScale *= input.height() / (float) input.width(); } else { xScale *= input.width() / (float) input.height(); } SkRect dst = SkRect::MakeXYWH(SK_Scalar1, SK_Scalar1, xScale * input.width(), yScale * input.height()); canvas.drawBitmapRect(input, NULL, dst); if (NULL != srcRect) { SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1, srcRect->fTop * yScale + SK_Scalar1, srcRect->fRight * xScale + SK_Scalar1, srcRect->fBottom * yScale + SK_Scalar1); SkPaint p; p.setColor(SK_ColorRED); p.setStyle(SkPaint::kStroke_Style); canvas.drawRect(r, p); } return bitmap; }
static void make_bitmap(SkBitmap* bitmap, GrContext* ctx, SkIRect* center) { SkDevice* dev; SkCanvas canvas; const int kFixed = 28; const int kStretchy = 8; const int kSize = 2*kFixed + kStretchy; #if SK_SUPPORT_GPU if (ctx) { dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, kSize, kSize); *bitmap = dev->accessBitmap(false); } else #endif { bitmap->setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize); bitmap->allocPixels(); dev = new SkDevice(*bitmap); } canvas.setDevice(dev)->unref(); canvas.clear(0); SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize)); const SkScalar strokeWidth = SkIntToScalar(6); const SkScalar radius = SkIntToScalar(kFixed) - strokeWidth/2; center->setXYWH(kFixed, kFixed, kStretchy, kStretchy); SkPaint paint; paint.setAntiAlias(true); paint.setColor(0xFFFF0000); canvas.drawRoundRect(r, radius, radius, paint); r.setXYWH(SkIntToScalar(kFixed), 0, SkIntToScalar(kStretchy), SkIntToScalar(kSize)); paint.setColor(0x8800FF00); canvas.drawRect(r, paint); r.setXYWH(0, SkIntToScalar(kFixed), SkIntToScalar(kSize), SkIntToScalar(kStretchy)); paint.setColor(0x880000FF); canvas.drawRect(r, paint); }
SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) { #ifdef SK_SUPPORT_GL #ifndef USE_OFFSCREEN aglSetWindowRef(gAGLContext, NULL); #endif #endif switch (fCanvasType) { case kRaster_CanvasType: canvas = this->INHERITED::beforeChildren(canvas); break; case kPicture_CanvasType: fPicture = new SkPicture; canvas = fPicture->beginRecording(9999, 9999); break; #ifdef SK_SUPPORT_GL case kOpenGL_CanvasType: { //SkGLCanvas::DeleteAllTextures(); // just for testing SkDevice* device = canvas->getDevice(); const SkBitmap& bitmap = device->accessBitmap(true); // first clear the raster bitmap, so we don't see any leftover bits bitmap.eraseColor(0); // now setup our glcanvas setup_offscreen_gl(bitmap, (WindowRef)this->getHWND()); fGLCanvas = new SkGLCanvas; fGLCanvas->setViewport(bitmap.width(), bitmap.height()); canvas = fGLCanvas; break; } #endif } if (fUseClip) { canvas->drawColor(0xFFFF88FF); canvas->clipPath(fClipPath); } return canvas; }
PassRefPtr<Image> ImageBuffer::copyImage() const { ASSERT(context() && context()->platformContext()); #if ENABLE(ACCELERATED_2D_CANVAS) context()->syncSoftwareCanvas(); #endif // Request for canvas bitmap; conversion required. if (context()->platformContext()->isRecording()) context()->platformContext()->convertToNonRecording(); SkCanvas* canvas = context()->platformContext()->mCanvas; SkDevice* device = canvas->getDevice(); const SkBitmap& orig = device->accessBitmap(false); SkBitmap copy; if (PlatformBridge::canSatisfyMemoryAllocation(orig.getSize())) orig.copyTo(©, orig.config()); SkBitmapRef* ref = new SkBitmapRef(copy); RefPtr<Image> image = BitmapImage::create(ref, 0); ref->unref(); return image; }
CGContextRef BitLockerSkia::cgContext() { SkDevice* device = m_canvas->getDevice(); ASSERT(device); if (!device) return 0; releaseIfNeeded(); const SkBitmap& bitmap = device->accessBitmap(true); bitmap.lockPixels(); void* pixels = bitmap.getPixels(); m_cgContext = CGBitmapContextCreate(pixels, device->width(), device->height(), 8, bitmap.rowBytes(), CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst); // Apply device matrix. CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1); contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -device->height()); CGContextConcatCTM(m_cgContext, contentsTransform); // Apply clip in device coordinates. CGMutablePathRef clipPath = CGPathCreateMutable(); SkRegion::Iterator iter(m_canvas->getTotalClip()); for (; !iter.done(); iter.next()) { IntRect rect = iter.rect(); CGPathAddRect(clipPath, 0, rect); } CGContextAddPath(m_cgContext, clipPath); CGContextClip(m_cgContext); CGPathRelease(clipPath); // Apply content matrix. const SkMatrix& skMatrix = m_canvas->getTotalMatrix(); CGAffineTransform affine = SkMatrixToCGAffineTransform(skMatrix); CGContextConcatCTM(m_cgContext, affine); return m_cgContext; }
bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& matrix, SkBitmap* result, SkIPoint* loc) { SkColorFilter* cf = fColorFilter; if (NULL == cf) { *result = src; return true; } SkDevice* dev = proxy->createDevice(src.width(), src.height()); if (NULL == dev) { return false; } OwnDeviceCanvas canvas(dev); SkPaint paint; paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setColorFilter(fColorFilter); canvas.drawSprite(src, 0, 0, &paint); *result = dev->accessBitmap(false); return true; }
void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) { if (renderInfo.baseTile->isLayerTile()) { g_bitmap->setIsOpaque(false); g_bitmap->eraseARGB(0, 0, 0, 0); } else { Color defaultBackground = Color::white; Color* background = renderInfo.tilePainter->background(); if (!background) { ALOGV("No background color for base layer!"); background = &defaultBackground; } ALOGV("setupCanvas use background on Base Layer %x", background->rgb()); g_bitmap->setIsOpaque(!background->hasAlpha()); g_bitmap->eraseARGB(background->alpha(), background->red(), background->green(), background->blue()); } SkDevice* device = new SkDevice(*g_bitmap); canvas->setDevice(device); device->unref(); }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(context() && context()->platformContext()); // Request for canvas bitmap; conversion required. if (context()->platformContext()->isRecording()) context()->platformContext()->convertToNonRecording(); // CAPPFIX_WEB_WEBGL SkCanvas* canvas = imageBufferCanvas(this); // CAPPFIX_WEB_WEBGL_END SkDevice* device = canvas->getDevice(); SkBitmap bitmap = device->accessBitmap(false); // if we can't see the pixels directly, call readPixels() to get a copy. // this could happen if the device is backed by a GPU. bitmap.lockPixels(); // balanced by our destructor, or explicitly if getPixels() fails if (!bitmap.getPixels()) { bitmap.unlockPixels(); SkIRect bounds = SkIRect::MakeWH(device->width(), device->height()); if (!canvas->readPixels(bounds, &bitmap)) return "data:,"; } return ImageToDataURL(bitmap, mimeType, quality); }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { m_context->platformContext()->makeGrContextCurrent(); SkDevice* device = context()->platformContext()->canvas()->getDevice(); return ImageToDataURL(device->accessBitmap(false), mimeType, quality); }
PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkCanvas& srcCanvas, const IntSize& size) { RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4); SkDevice* srcDevice = srcCanvas.getDevice(); SkBitmap::Config srcConfig = srcDevice->accessBitmap(false).config(); if (srcConfig == SkBitmap::kNo_Config) { // This is an empty SkBitmap that could not be configured. ASSERT(!size.width() || !size.height()); return result.release(); } unsigned char* data = result->data(); if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height()) memset(data, 0, result->length()); int originX = rect.x(); int destX = 0; if (originX < 0) { destX = -originX; originX = 0; } int endX = rect.maxX(); if (endX > size.width()) endX = size.width(); int numColumns = endX - originX; if (numColumns <= 0) return result.release(); int originY = rect.y(); int destY = 0; if (originY < 0) { destY = -originY; originY = 0; } int endY = rect.maxY(); if (endY > size.height()) endY = size.height(); int numRows = endY - originY; if (numRows <= 0) return result.release(); ASSERT(srcConfig == SkBitmap::kARGB_8888_Config); unsigned destBytesPerRow = 4 * rect.width(); SkBitmap srcBitmap; srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, destBytesPerRow); srcBitmap.setPixels(data); //srcDevice.readPixels(SkIRect::MakeXYWH(originX, originY, numColumns, numRows), &srcBitmap, SkCanvas::kNative_Premul_Config8888); SkCanvas::Config8888 config8888; if (multiplied == Premultiplied) config8888 = SkCanvas::kRGBA_Premul_Config8888; else config8888 = SkCanvas::kRGBA_Unpremul_Config8888; srcCanvas.readPixels(&srcBitmap, originX, originY, SkCanvas::kNative_Premul_Config8888); unsigned char* destRow = data + destY * destBytesPerRow + destX * 4; // Do conversion of byte order and alpha divide (if necessary) for (int y = 0; y < numRows; ++y) { SkPMColor* srcBitmapRow = srcBitmap.getAddr32(0, y); for (int x = 0; x < numColumns; ++x) { SkPMColor srcPMColor = srcBitmapRow[x]; unsigned char* destPixel = &destRow[x * 4]; if (multiplied == Unmultiplied) { unsigned char a = SkGetPackedA32(srcPMColor); destPixel[0] = a ? SkGetPackedR32(srcPMColor) * 255 / a : 0; destPixel[1] = a ? SkGetPackedG32(srcPMColor) * 255 / a : 0; destPixel[2] = a ? SkGetPackedB32(srcPMColor) * 255 / a : 0; destPixel[3] = a; } else { // Input and output are both pre-multiplied, we just need to re-arrange the // bytes from the bitmap format to RGBA. destPixel[0] = SkGetPackedR32(srcPMColor); destPixel[1] = SkGetPackedG32(srcPMColor); destPixel[2] = SkGetPackedB32(srcPMColor); destPixel[3] = SkGetPackedA32(srcPMColor); } } destRow += destBytesPerRow; } return result.release(); }
static void blowup(SkCanvas* canvas, const SkIRect& src, const SkRect& dst) { SkDevice* device = canvas->getDevice(); const SkBitmap& bm = device->accessBitmap(false); canvas->drawBitmapRect(bm, &src, dst, NULL); }
virtual void onDraw(SkCanvas* canvas) { SkDevice* device = canvas->getDevice(); GrRenderTarget* target = (GrRenderTarget*) device->accessRenderTarget(); GrContext* ctx = GetGr(); if (ctx && target) { SkPMColor gTextureData[(2 * S) * (2 * S)]; static const int stride = 2 * S; static const SkPMColor gray = SkPackARGB32(0x40, 0x40, 0x40, 0x40); static const SkPMColor white = SkPackARGB32(0xff, 0xff, 0xff, 0xff); static const SkPMColor red = SkPackARGB32(0x80, 0x80, 0x00, 0x00); static const SkPMColor blue = SkPackARGB32(0x80, 0x00, 0x00, 0x80); static const SkPMColor green = SkPackARGB32(0x80, 0x00, 0x80, 0x00); static const SkPMColor black = SkPackARGB32(0x00, 0x00, 0x00, 0x00); for (int i = 0; i < 2; ++i) { int offset = 0; // fill upper-left for (int y = 0; y < S; ++y) { for (int x = 0; x < S; ++x) { gTextureData[offset + y * stride + x] = gray; } } // fill upper-right offset = S; for (int y = 0; y < S; ++y) { for (int x = 0; x < S; ++x) { gTextureData[offset + y * stride + x] = white; } } // fill lower left offset = S * stride; for (int y = 0; y < S; ++y) { for (int x = 0; x < S; ++x) { gTextureData[offset + y * stride + x] = black; } } // fill lower right offset = S * stride + S; for (int y = 0; y < S; ++y) { for (int x = 0; x < S; ++x) { gTextureData[offset + y * stride + x] = gray; } } GrTextureDesc desc; desc.fAALevel = kNone_GrAALevel; // use RT flag bit because in GL it makes the texture be bottom-up desc.fFlags = i ? kRenderTarget_GrTextureFlagBit : kNone_GrTextureFlags; desc.fConfig = kSkia8888_PM_GrPixelConfig; desc.fWidth = 2 * S; desc.fHeight = 2 * S; GrTexture* texture = ctx->createUncachedTexture(desc, gTextureData, 0); if (!texture) { return; } GrAutoUnref au(texture); ctx->setClip(GrRect::MakeWH(2*S, 2*S)); ctx->setRenderTarget(target); GrPaint paint; paint.reset(); paint.fColor = 0xffffffff; paint.fSrcBlendCoeff = kOne_BlendCoeff; paint.fDstBlendCoeff = kISA_BlendCoeff; GrMatrix vm; if (i) { vm.setRotate(90 * SK_Scalar1, S * SK_Scalar1, S * SK_Scalar1); } else { vm.reset(); } ctx->setMatrix(vm); GrMatrix tm; tm = vm; tm.postIDiv(2*S, 2*S); paint.textureSampler(0)->setMatrix(tm); paint.setTexture(0, texture); ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S)); // now update the lower right of the texture in first pass // or upper right in second pass offset = 0; for (int y = 0; y < S; ++y) { for (int x = 0; x < S; ++x) { gTextureData[offset + y * stride + x] = ((x + y) % 2) ? (i ? green : red) : blue; } } texture->writePixels(S, (i ? 0 : S), S, S, texture->config(), gTextureData, 4 * stride); ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S)); } } }