Make all pixel ops go thru ctx so we can correctly flush. Unify two texture upload code paths.
Review URL: http://codereview.appspot.com/5373108/ git-svn-id: http://skia.googlecode.com/svn/trunk@2701 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
aa336da083
commit
6f3795105b
@ -124,9 +124,9 @@ protected:
|
||||
((x + y) % 2) ? (i ? green : red) : blue;
|
||||
}
|
||||
}
|
||||
// BUG: uploadTextureData doesn't force a flush
|
||||
ctx->flush();
|
||||
texture->uploadTextureData(S, i ? 0 : S, S, S, gTextureData, 4 * stride);
|
||||
texture->writePixels(S, (i ? 0 : S), S, S,
|
||||
texture->config(), gTextureData,
|
||||
4 * stride);
|
||||
ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));
|
||||
}
|
||||
}
|
||||
|
@ -445,10 +445,10 @@ public:
|
||||
* FlushBits.
|
||||
*/
|
||||
void flush(int flagsBitfield = 0);
|
||||
|
||||
|
||||
/**
|
||||
* Reads a rectangle of pixels from a render target.
|
||||
* @param renderTarget the render target to read from. NULL means the
|
||||
* @param target the render target to read from. NULL means the
|
||||
* current render target.
|
||||
* @param left left edge of the rectangle to read (inclusive)
|
||||
* @param top top edge of the rectangle to read (inclusive)
|
||||
@ -456,42 +456,88 @@ public:
|
||||
* @param height height of rectangle to read in pixels.
|
||||
* @param config the pixel config of the destination buffer
|
||||
* @param buffer memory to read the rectangle into.
|
||||
* @param rowBytes number of bytes bewtween consecueive rows. Zero
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*
|
||||
* @return true if the read succeeded, false if not. The read can fail
|
||||
* because of a unsupported pixel config or because no render
|
||||
* because of an unsupported pixel config or because no render
|
||||
* target is currently set.
|
||||
*/
|
||||
bool readRenderTargetPixels(GrRenderTarget* target,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes = 0);
|
||||
size_t rowBytes) {
|
||||
return this->internalReadRenderTargetPixels(target, left, top,
|
||||
width, height,
|
||||
config, buffer,
|
||||
rowBytes, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the src pixels [buffer, rowbytes, pixelconfig] into a render target
|
||||
* at the specified rectangle.
|
||||
* @param target the render target to write into. NULL means the
|
||||
* current render target.
|
||||
* @param left left edge of the rectangle to write (inclusive)
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
* @param height height of rectangle to write in pixels.
|
||||
* @param config the pixel config of the source buffer
|
||||
* @param buffer memory to read the rectangle from.
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*/
|
||||
void writeRenderTargetPixels(GrRenderTarget* target,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
this->internalWriteRenderTargetPixels(target, left, top, width, height,
|
||||
config, buffer, rowBytes, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a rectangle of pixels from a texture.
|
||||
* @param texture the render target to read from.
|
||||
* @param texture the texture to read from.
|
||||
* @param left left edge of the rectangle to read (inclusive)
|
||||
* @param top top edge of the rectangle to read (inclusive)
|
||||
* @param width width of rectangle to read in pixels.
|
||||
* @param height height of rectangle to read in pixels.
|
||||
* @param config the pixel config of the destination buffer
|
||||
* @param buffer memory to read the rectangle into.
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*
|
||||
* @return true if the read succeeded, false if not. The read can fail
|
||||
* because of a unsupported pixel config.
|
||||
* because of an unsupported pixel config.
|
||||
*/
|
||||
bool readTexturePixels(GrTexture* target,
|
||||
bool readTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer);
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes) {
|
||||
return this->internalReadTexturePixels(texture, left, top,
|
||||
width, height,
|
||||
config, buffer, rowBytes, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the src pixels [buffer, stride, pixelconfig] into the current
|
||||
* render-target at the specified rectangle.
|
||||
* Writes a rectangle of pixels to a texture.
|
||||
* @param texture the render target to read from.
|
||||
* @param left left edge of the rectangle to write (inclusive)
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
* @param height height of rectangle to write in pixels.
|
||||
* @param config the pixel config of the source buffer
|
||||
* @param buffer memory to read pixels from
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*/
|
||||
void writePixels(int left, int top, int width, int height,
|
||||
GrPixelConfig, const void* buffer, size_t stride);
|
||||
|
||||
void writeTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
this->internalWriteTexturePixels(texture, left, top, width, height,
|
||||
config, buffer, rowBytes, 0);
|
||||
}
|
||||
/**
|
||||
* Applies a 1D convolution kernel in the X direction to a rectangle of
|
||||
* pixels from a given texture.
|
||||
@ -654,7 +700,43 @@ private:
|
||||
float imageIncrement[2],
|
||||
const float* kernel,
|
||||
int kernelWidth);
|
||||
|
||||
|
||||
/**
|
||||
* Flags to the internal read/write pixels funcs
|
||||
*/
|
||||
enum PixelOpsFlags {
|
||||
kDontFlush_PixelOpsFlag = 0x1,
|
||||
};
|
||||
|
||||
bool internalReadRenderTargetPixels(GrRenderTarget* target,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes, uint32_t flags);
|
||||
|
||||
void internalWriteRenderTargetPixels(GrRenderTarget* target,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig, const void* buffer,
|
||||
size_t rowBytes, uint32_t flags);
|
||||
|
||||
bool internalReadTexturePixels(GrTexture* texture,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes, uint32_t flags);
|
||||
|
||||
void internalWriteTexturePixels(GrTexture* texture,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes, uint32_t flags);
|
||||
// needed for access to internalWriteTexturePixels. TODO: make GrContext
|
||||
// be a facade for an internal class. Then functions that are public on the
|
||||
// internal class would have only be callable in src/gpu. The facade would
|
||||
// only have to functions necessary for clients.
|
||||
friend class GrAtlas;
|
||||
|
||||
// computes vertex layout bits based on the paint. If paint expresses
|
||||
// a texture for a stage, the stage coords will be bound to postitions
|
||||
// unless hasTexCoords[s]==true in which case stage s's input coords
|
||||
|
@ -123,12 +123,29 @@ public:
|
||||
* @param height height of rectangle to read in pixels.
|
||||
* @param config the pixel config of the destination buffer
|
||||
* @param buffer memory to read the rectangle into.
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*
|
||||
* @return true if the read succeeded, false if not. The read can fail
|
||||
* because of a unsupported pixel config.
|
||||
* because of an unsupported pixel config.
|
||||
*/
|
||||
bool readPixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer);
|
||||
GrPixelConfig config, void* buffer, size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Copy the src pixels [buffer, rowbytes, pixelconfig] into the render
|
||||
* target at the specified rectangle.
|
||||
* @param left left edge of the rectangle to write (inclusive)
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
* @param height height of rectangle to write in pixels.
|
||||
* @param config the pixel config of the source buffer
|
||||
* @param buffer memory to read the rectangle from.
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*/
|
||||
void writePixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer, size_t rowBytes);
|
||||
|
||||
// a MSAA RT may require explicit resolving , it may auto-resolve (e.g. FBO
|
||||
// 0 in GL), or be unresolvable because the client didn't give us the
|
||||
|
@ -54,38 +54,37 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a subrectangle of texels in the texture.
|
||||
*
|
||||
* @param x left edge of rectangle to update
|
||||
* @param y top edge of rectangle to update
|
||||
* @param width width of rectangle to update
|
||||
* @param height height of rectangle to update
|
||||
* @param srcData width*height texels of data in same format that was
|
||||
* used at texture creation.
|
||||
* @param rowBytes number of bytes per row in srcData, 0 means rows are
|
||||
* packed
|
||||
*/
|
||||
virtual void uploadTextureData(int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
const void* srcData,
|
||||
size_t rowBytes) = 0;
|
||||
|
||||
/**
|
||||
* Reads a rectangle of pixels from the texture.
|
||||
* Read a rectangle of pixels from the texture.
|
||||
* @param left left edge of the rectangle to read (inclusive)
|
||||
* @param top top edge of the rectangle to read (inclusive)
|
||||
* @param width width of rectangle to read in pixels.
|
||||
* @param height height of rectangle to read in pixels.
|
||||
* @param config the pixel config of the destination buffer
|
||||
* @param buffer memory to read the rectangle into.
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*
|
||||
* @return true if the read succeeded, false if not. The read can fail
|
||||
* because of a unsupported pixel config.
|
||||
*/
|
||||
bool readPixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer);
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Writes a rectangle of pixels to the texture.
|
||||
* @param left left edge of the rectangle to write (inclusive)
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
* @param height height of rectangle to write in pixels.
|
||||
* @param config the pixel config of the source buffer
|
||||
* @param buffer memory to read pixels from
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*/
|
||||
void writePixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Retrieves the render target underlying this texture that can be passed to
|
||||
|
@ -177,10 +177,10 @@ public:
|
||||
// need to send the raster bits to the (gpu) window
|
||||
fGrContext->setRenderTarget(fGrRenderTarget);
|
||||
const SkBitmap& bm = win->getBitmap();
|
||||
fGrContext->writePixels(0, 0, bm.width(), bm.height(),
|
||||
kSkia8888_PM_GrPixelConfig,
|
||||
bm.getPixels(),
|
||||
bm.rowBytes());
|
||||
fGrRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
|
||||
kSkia8888_PM_GrPixelConfig,
|
||||
bm.getPixels(),
|
||||
bm.rowBytes());
|
||||
}
|
||||
}
|
||||
win->presentGL();
|
||||
@ -211,7 +211,7 @@ public:
|
||||
desc.fStencilBits = 8;
|
||||
desc.fSampleCnt = 0;
|
||||
desc.fRenderTargetHandle = 0;
|
||||
fGrRenderTarget = fNullGrContext->createPlatformRenderTarget(desc);
|
||||
fNullGrRenderTarget = fNullGrContext->createPlatformRenderTarget(desc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
#include "GrAtlas.h"
|
||||
#include "GrContext.h"
|
||||
#include "GrGpu.h"
|
||||
#include "GrRectanizer.h"
|
||||
#include "GrPlotMgr.h"
|
||||
@ -109,7 +110,14 @@ bool GrAtlas::addSubImage(int width, int height, const void* image,
|
||||
image = storage.get();
|
||||
}
|
||||
adjustForPlot(loc, fPlot);
|
||||
fTexture->uploadTextureData(loc->fX, loc->fY, dstW, dstH, image, 0);
|
||||
GrContext* context = fTexture->getContext();
|
||||
// We call the internal version so that we don't force a flush. We assume
|
||||
// our caller is smart and hasn't referenced the part of the texture we're
|
||||
// about to update since the last flush.
|
||||
context->internalWriteTexturePixels(fTexture, loc->fX, loc->fY,
|
||||
dstW, dstH, fTexture->config(),
|
||||
image, 0,
|
||||
GrContext::kDontFlush_PixelOpsFlag);
|
||||
|
||||
// now tell the caller to skip the top/left BORDER
|
||||
loc->fX += BORDER;
|
||||
|
@ -1637,28 +1637,59 @@ void GrContext::flushDrawBuffer() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GrContext::readTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer) {
|
||||
void GrContext::internalWriteTexturePixels(GrTexture* texture,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config,
|
||||
const void* buffer,
|
||||
size_t rowBytes,
|
||||
uint32_t flags) {
|
||||
SK_TRACE_EVENT0("GrContext::writeTexturePixels");
|
||||
if (!(kDontFlush_PixelOpsFlag & flags)) {
|
||||
this->flush();
|
||||
}
|
||||
// TODO: use scratch texture to perform conversion
|
||||
if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
|
||||
GrPixelConfigIsUnpremultiplied(config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fGpu->writeTexturePixels(texture, left, top, width, height,
|
||||
config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
bool GrContext::internalReadTexturePixels(GrTexture* texture,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config,
|
||||
void* buffer,
|
||||
size_t rowBytes,
|
||||
uint32_t flags) {
|
||||
SK_TRACE_EVENT0("GrContext::readTexturePixels");
|
||||
|
||||
// TODO: code read pixels for textures that aren't rendertargets
|
||||
|
||||
this->flush();
|
||||
if (!(kDontFlush_PixelOpsFlag & flags)) {
|
||||
this->flush();
|
||||
}
|
||||
GrRenderTarget* target = texture->asRenderTarget();
|
||||
if (NULL != target) {
|
||||
return this->readRenderTargetPixels(target,
|
||||
left, top, width, height,
|
||||
config, buffer, 0);
|
||||
return this->internalReadRenderTargetPixels(target,
|
||||
left, top, width, height,
|
||||
config, buffer, rowBytes,
|
||||
flags);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes) {
|
||||
bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config,
|
||||
void* buffer,
|
||||
size_t rowBytes,
|
||||
uint32_t flags) {
|
||||
SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
|
||||
if (NULL == target) {
|
||||
target = fGpu->getRenderTarget();
|
||||
@ -1675,7 +1706,9 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
||||
return false;
|
||||
}
|
||||
|
||||
this->flush();
|
||||
if (!(kDontFlush_PixelOpsFlag & flags)) {
|
||||
this->flush();
|
||||
}
|
||||
|
||||
GrTexture* src = target->asTexture();
|
||||
bool swapRAndB = NULL != src &&
|
||||
@ -1751,16 +1784,25 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
||||
config, buffer, rowBytes, flipY);
|
||||
}
|
||||
|
||||
void GrContext::writePixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t stride) {
|
||||
SK_TRACE_EVENT0("GrContext::writePixels");
|
||||
void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config,
|
||||
const void* buffer,
|
||||
size_t rowBytes,
|
||||
uint32_t flags) {
|
||||
SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
|
||||
|
||||
if (NULL == target) {
|
||||
target = fGpu->getRenderTarget();
|
||||
if (NULL == target) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: when underlying api has a direct way to do this we should use it
|
||||
// (e.g. glDrawPixels on desktop GL).
|
||||
|
||||
this->flush(kForceCurrentRenderTarget_FlushBit);
|
||||
|
||||
const GrTextureDesc desc = {
|
||||
kNone_GrTextureFlags, kNone_GrAALevel, width, height, { config }
|
||||
};
|
||||
@ -1769,7 +1811,8 @@ void GrContext::writePixels(int left, int top, int width, int height,
|
||||
if (NULL == texture) {
|
||||
return;
|
||||
}
|
||||
texture->uploadTextureData(0, 0, width, height, buffer, stride);
|
||||
this->internalWriteTexturePixels(texture, 0, 0, width, height,
|
||||
config, buffer, rowBytes, flags);
|
||||
|
||||
GrDrawTarget::AutoStateRestore asr(fGpu);
|
||||
reset_target_state(fGpu);
|
||||
@ -1777,7 +1820,7 @@ void GrContext::writePixels(int left, int top, int width, int height,
|
||||
GrMatrix matrix;
|
||||
matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
|
||||
fGpu->setViewMatrix(matrix);
|
||||
|
||||
fGpu->setRenderTarget(target);
|
||||
fGpu->setTexture(0, texture);
|
||||
|
||||
GrSamplerState sampler;
|
||||
|
@ -35,8 +35,7 @@ void GrGLTexture::init(GrGpuGL* gpu,
|
||||
fTexIDObj = new GrGLTexID(GPUGL->glInterface(),
|
||||
textureDesc.fTextureID,
|
||||
textureDesc.fOwnsID);
|
||||
fUploadFormat = textureDesc.fUploadFormat;
|
||||
fUploadType = textureDesc.fUploadType;
|
||||
fInternalFormat = textureDesc.fInternalFormat;
|
||||
fOrientation = textureDesc.fOrientation;
|
||||
|
||||
if (NULL != rtDesc) {
|
||||
@ -86,83 +85,6 @@ void GrGLTexture::onAbandon() {
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLTexture::uploadTextureData(int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
const void* srcData,
|
||||
size_t rowBytes) {
|
||||
GrIRect bounds = GrIRect::MakeWH(this->width(), this->height());
|
||||
GrIRect subrect = GrIRect::MakeXYWH(x,y,width, height);
|
||||
if (!bounds.contains(subrect)) {
|
||||
return;
|
||||
}
|
||||
GPUGL->setSpareTextureUnit();
|
||||
|
||||
// ES2 glCompressedTexSubImage2D doesn't support any formats
|
||||
// (at least without extensions)
|
||||
GrAssert(fUploadFormat != GR_GL_PALETTE8_RGBA8);
|
||||
|
||||
// in case we need a temporary, trimmed copy of the src pixels
|
||||
SkAutoSMalloc<128 * 128> tempStorage;
|
||||
|
||||
size_t bpp = GrBytesPerPixel(this->config());
|
||||
size_t trimRowBytes = width * bpp;
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
}
|
||||
/*
|
||||
* check whether to allocate a temporary buffer for flipping y or
|
||||
* because our srcData has extra bytes past each row. If so, we need
|
||||
* to trim those off here, since GL ES may not let us specify
|
||||
* GL_UNPACK_ROW_LENGTH.
|
||||
*/
|
||||
bool restoreGLRowLength = false;
|
||||
bool flipY = kBottomUp_Orientation == fOrientation;
|
||||
if (GPUGL->glCaps().fUnpackRowLengthSupport && !flipY) {
|
||||
// can't use this for flipping, only non-neg values allowed. :(
|
||||
if (srcData && rowBytes != trimRowBytes) {
|
||||
GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
|
||||
restoreGLRowLength = true;
|
||||
}
|
||||
} else {
|
||||
if (srcData && (trimRowBytes != rowBytes || flipY)) {
|
||||
// copy the data into our new storage, skipping the trailing bytes
|
||||
size_t trimSize = height * trimRowBytes;
|
||||
const char* src = (const char*)srcData;
|
||||
if (flipY) {
|
||||
src += (height - 1) * rowBytes;
|
||||
}
|
||||
char* dst = (char*)tempStorage.reset(trimSize);
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy(dst, src, trimRowBytes);
|
||||
if (flipY) {
|
||||
src -= rowBytes;
|
||||
} else {
|
||||
src += rowBytes;
|
||||
}
|
||||
dst += trimRowBytes;
|
||||
}
|
||||
// now point srcData to our copied version
|
||||
srcData = tempStorage.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (flipY) {
|
||||
y = this->height() - (y + height);
|
||||
}
|
||||
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, fTexIDObj->id()));
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
|
||||
GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, x, y, width, height,
|
||||
fUploadFormat, fUploadType, srcData));
|
||||
|
||||
if (restoreGLRowLength) {
|
||||
GrAssert(GPUGL->glCaps().fUnpackRowLengthSupport);
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t GrGLTexture::getTextureHandle() const {
|
||||
return fTexIDObj->id();
|
||||
}
|
||||
|
@ -64,9 +64,8 @@ public:
|
||||
int fHeight;
|
||||
GrPixelConfig fConfig;
|
||||
GrGLuint fTextureID;
|
||||
GrGLenum fInternalFormat;
|
||||
bool fOwnsID;
|
||||
GrGLenum fUploadFormat;
|
||||
GrGLenum fUploadType;
|
||||
Orientation fOrientation;
|
||||
};
|
||||
|
||||
@ -82,13 +81,6 @@ public:
|
||||
|
||||
virtual ~GrGLTexture() { this->release(); }
|
||||
|
||||
// overrides of GrTexture
|
||||
virtual void uploadTextureData(int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
const void* srcData,
|
||||
size_t rowBytes);
|
||||
virtual intptr_t getTextureHandle() const;
|
||||
|
||||
// these functions
|
||||
@ -103,8 +95,7 @@ public:
|
||||
}
|
||||
GrGLuint textureID() const { return fTexIDObj->id(); }
|
||||
|
||||
GrGLenum uploadFormat() const { return fUploadFormat; }
|
||||
GrGLenum uploadType() const { return fUploadType; }
|
||||
GrGLenum internalFormat() const { return fInternalFormat; }
|
||||
|
||||
// Ganesh assumes texture coordinates have their origin
|
||||
// in the top-left corner of the image. OpenGL, however,
|
||||
@ -128,8 +119,7 @@ private:
|
||||
TexParams fTexParams;
|
||||
GrGpu::ResetTimestamp fTexParamsTimestamp;
|
||||
GrGLTexID* fTexIDObj;
|
||||
GrGLenum fUploadFormat;
|
||||
GrGLenum fUploadType;
|
||||
GrGLenum fInternalFormat;
|
||||
Orientation fOrientation;
|
||||
|
||||
void init(GrGpuGL* gpu,
|
||||
|
@ -253,6 +253,17 @@ bool GrGpu::readPixels(GrRenderTarget* target,
|
||||
config, buffer, rowBytes, invertY);
|
||||
}
|
||||
|
||||
void GrGpu::writeTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
GrAssert(GrPixelConfigIsUnpremultiplied(config) ==
|
||||
GrPixelConfigIsUnpremultiplied(texture->config()));
|
||||
this->handleDirtyContext();
|
||||
this->onWriteTexturePixels(texture, left, top, width, height,
|
||||
config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
|
||||
|
@ -245,6 +245,22 @@ public:
|
||||
GrPixelConfig config, void* buffer, size_t rowBytes,
|
||||
bool invertY);
|
||||
|
||||
/**
|
||||
* Updates the pixels in a rectangle of a texture.
|
||||
* @param left left edge of the rectangle to write (inclusive)
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
* @param height height of rectangle to write in pixels.
|
||||
* @param config the pixel config of the source buffer
|
||||
* @param buffer memory to read pixels from
|
||||
* @param rowBytes number of bytes bewtween consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
*/
|
||||
void writeTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes);
|
||||
|
||||
const GrGpuStats& getStats() const;
|
||||
void resetStats();
|
||||
void printStats() const;
|
||||
@ -402,6 +418,12 @@ protected:
|
||||
size_t rowBytes,
|
||||
bool invertY) = 0;
|
||||
|
||||
// overridden by API-specific derived class to perform the texture update
|
||||
virtual void onWriteTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) = 0;
|
||||
|
||||
// called to program the vertex data, indexCount will be 0 if drawing non-
|
||||
// indexed geometry. The subclass may adjust the startVertex and/or
|
||||
// startIndex since it may have already accounted for these in the setup.
|
||||
|
@ -523,10 +523,10 @@ void GrGpuGL::onResetContext() {
|
||||
}
|
||||
|
||||
GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) {
|
||||
GrGLenum internalFormat; // we don't need this value
|
||||
GrGLenum dontCare;
|
||||
GrGLTexture::Desc glTexDesc;
|
||||
if (!this->canBeTexture(desc.fConfig, &internalFormat,
|
||||
&glTexDesc.fUploadFormat, &glTexDesc.fUploadType)) {
|
||||
if (!this->canBeTexture(desc.fConfig, &glTexDesc.fInternalFormat,
|
||||
&dontCare, &dontCare)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -639,9 +639,8 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc)
|
||||
if (isTexture) {
|
||||
GrGLTexture::Desc texDesc;
|
||||
GrGLenum dontCare;
|
||||
if (!canBeTexture(desc.fConfig, &dontCare,
|
||||
&texDesc.fUploadFormat,
|
||||
&texDesc.fUploadType)) {
|
||||
if (!canBeTexture(desc.fConfig, &texDesc.fInternalFormat,
|
||||
&dontCare, &dontCare)) {
|
||||
return NULL;
|
||||
}
|
||||
texDesc.fWidth = desc.fWidth;
|
||||
@ -675,44 +674,82 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGpuGL::allocateAndUploadTexData(const GrGLTexture::Desc& desc,
|
||||
GrGLenum internalFormat,
|
||||
const void* data,
|
||||
size_t rowBytes) {
|
||||
// we assume the texture is bound
|
||||
void GrGpuGL::onWriteTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
|
||||
|
||||
size_t bpp = GrBytesPerPixel(desc.fConfig);
|
||||
size_t trimRowBytes = desc.fWidth * bpp;
|
||||
this->setSpareTextureUnit();
|
||||
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID()));
|
||||
GrGLTexture::Desc desc;
|
||||
desc.fConfig = glTex->config();
|
||||
desc.fWidth = glTex->width();
|
||||
desc.fHeight = glTex->height();
|
||||
desc.fOrientation = glTex->orientation();
|
||||
desc.fTextureID = glTex->textureID();
|
||||
desc.fInternalFormat = glTex->internalFormat();
|
||||
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
this->uploadTexData(desc, left, top, width, height, config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
void GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dataConfig,
|
||||
const void* data,
|
||||
size_t rowBytes) {
|
||||
GrIRect bounds = GrIRect::MakeWH(desc.fWidth, desc.fHeight);
|
||||
GrIRect subrect = GrIRect::MakeXYWH(left, top, width, height);
|
||||
if (!bounds.contains(subrect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ES2 glCompressedTexSubImage2D doesn't support any formats
|
||||
// (at least without extensions)
|
||||
GrAssert(desc.fInternalFormat != GR_GL_PALETTE8_RGBA8 ||
|
||||
bounds == subrect);
|
||||
|
||||
// in case we need a temporary, trimmed copy of the src pixels
|
||||
SkAutoSMalloc<128 * 128> tempStorage;
|
||||
|
||||
GrGLenum dontCare;
|
||||
GrGLenum externalFormat;
|
||||
GrGLenum externalType;
|
||||
if (!this->canBeTexture(dataConfig, &dontCare,
|
||||
&externalFormat, &externalType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bpp = GrBytesPerPixel(dataConfig);
|
||||
size_t trimRowBytes = width * bpp;
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
}
|
||||
/*
|
||||
* check whether to allocate a temporary buffer for flipping y or
|
||||
* because our data has extra bytes past each row. If so, we need
|
||||
* to trim those off here, since GL ES doesn't let us specify
|
||||
* GL_UNPACK_ROW_LENGTH.
|
||||
* check whether to allocate a temporary buffer for flipping y or
|
||||
* because our srcData has extra bytes past each row. If so, we need
|
||||
* to trim those off here, since GL ES may not let us specify
|
||||
* GL_UNPACK_ROW_LENGTH.
|
||||
*/
|
||||
bool restoreGLRowLength = false;
|
||||
bool flipY = GrGLTexture::kBottomUp_Orientation == desc.fOrientation;
|
||||
if (this->glCaps().fUnpackRowLengthSupport && !flipY) {
|
||||
if (data && rowBytes != trimRowBytes) {
|
||||
// can't use this for flipping, only non-neg values allowed. :(
|
||||
if (rowBytes != trimRowBytes) {
|
||||
GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
|
||||
restoreGLRowLength = true;
|
||||
}
|
||||
} else {
|
||||
if (data && (trimRowBytes != rowBytes || flipY)) {
|
||||
if (trimRowBytes != rowBytes || flipY) {
|
||||
// copy the data into our new storage, skipping the trailing bytes
|
||||
size_t trimSize = desc.fHeight * trimRowBytes;
|
||||
size_t trimSize = height * trimRowBytes;
|
||||
const char* src = (const char*)data;
|
||||
if (flipY) {
|
||||
src += (desc.fHeight - 1) * rowBytes;
|
||||
src += (height - 1) * rowBytes;
|
||||
}
|
||||
char* dst = (char*)tempStorage.reset(trimSize);
|
||||
for (int y = 0; y < desc.fHeight; y++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy(dst, src, trimRowBytes);
|
||||
if (flipY) {
|
||||
src -= rowBytes;
|
||||
@ -721,31 +758,27 @@ void GrGpuGL::allocateAndUploadTexData(const GrGLTexture::Desc& desc,
|
||||
}
|
||||
dst += trimRowBytes;
|
||||
}
|
||||
// now point data to our trimmed version
|
||||
// now point dat to our copied version
|
||||
data = tempStorage.get();
|
||||
rowBytes = trimRowBytes;
|
||||
}
|
||||
}
|
||||
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
|
||||
if (kIndex_8_GrPixelConfig == desc.fConfig &&
|
||||
this->getCaps().f8BitPaletteSupport) {
|
||||
// ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
|
||||
GrGLsizei imageSize = desc.fWidth * desc.fHeight +
|
||||
kGrColorTableSize;
|
||||
GL_CALL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, desc.fUploadFormat,
|
||||
desc.fWidth, desc.fHeight,
|
||||
0, imageSize, data));
|
||||
if (this->glCaps().fUnpackRowLengthSupport) {
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
}
|
||||
if (bounds == subrect) {
|
||||
GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, desc.fInternalFormat,
|
||||
desc.fWidth, desc.fHeight, 0,
|
||||
externalFormat, externalType, data));
|
||||
} else {
|
||||
GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
|
||||
desc.fWidth, desc.fHeight, 0,
|
||||
desc.fUploadFormat, desc.fUploadType, data));
|
||||
if (this->glCaps().fUnpackRowLengthSupport) {
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
if (flipY) {
|
||||
top = desc.fHeight - (top + height);
|
||||
}
|
||||
GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, left, top, width, height,
|
||||
externalFormat, externalType, data));
|
||||
}
|
||||
|
||||
if (restoreGLRowLength) {
|
||||
GrAssert(this->glCaps().fUnpackRowLengthSupport);
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -856,7 +889,8 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
|
||||
|
||||
GrGLTexture::Desc glTexDesc;
|
||||
GrGLRenderTarget::Desc glRTDesc;
|
||||
GrGLenum internalFormat;
|
||||
GrGLenum externalFormat;
|
||||
GrGLenum externalType;
|
||||
|
||||
glTexDesc.fWidth = desc.fWidth;
|
||||
glTexDesc.fHeight = desc.fHeight;
|
||||
@ -871,9 +905,9 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
|
||||
|
||||
bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
|
||||
if (!canBeTexture(desc.fConfig,
|
||||
&internalFormat,
|
||||
&glTexDesc.fUploadFormat,
|
||||
&glTexDesc.fUploadType)) {
|
||||
&glTexDesc.fInternalFormat,
|
||||
&externalFormat,
|
||||
&externalType)) {
|
||||
return return_null_texture();
|
||||
}
|
||||
|
||||
@ -928,7 +962,14 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
|
||||
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
|
||||
GR_GL_TEXTURE_WRAP_T,
|
||||
initialTexParams.fWrapT));
|
||||
this->allocateAndUploadTexData(glTexDesc, internalFormat,srcData, rowBytes);
|
||||
if (NULL == srcData) {
|
||||
GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, glTexDesc.fInternalFormat,
|
||||
glTexDesc.fWidth, glTexDesc.fHeight, 0,
|
||||
externalFormat, externalType, NULL));
|
||||
} else {
|
||||
this->uploadTexData(glTexDesc, 0, 0, glTexDesc.fWidth, glTexDesc.fHeight,
|
||||
desc.fConfig, srcData, rowBytes);
|
||||
}
|
||||
|
||||
GrGLTexture* tex;
|
||||
if (renderTarget) {
|
||||
@ -2075,51 +2116,51 @@ void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
|
||||
|
||||
bool GrGpuGL::canBeTexture(GrPixelConfig config,
|
||||
GrGLenum* internalFormat,
|
||||
GrGLenum* format,
|
||||
GrGLenum* type) {
|
||||
GrGLenum* externalFormat,
|
||||
GrGLenum* externalType) {
|
||||
switch (config) {
|
||||
case kRGBA_8888_PM_GrPixelConfig:
|
||||
case kRGBA_8888_UPM_GrPixelConfig:
|
||||
*format = GR_GL_RGBA;
|
||||
*externalFormat = GR_GL_RGBA;
|
||||
*internalFormat = GR_GL_RGBA;
|
||||
*type = GR_GL_UNSIGNED_BYTE;
|
||||
*externalType = GR_GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case kBGRA_8888_PM_GrPixelConfig:
|
||||
case kBGRA_8888_UPM_GrPixelConfig:
|
||||
if (!fGLCaps.fBGRAFormatSupport) {
|
||||
return false;
|
||||
}
|
||||
*format = GR_GL_BGRA;
|
||||
*externalFormat = GR_GL_BGRA;
|
||||
if (fGLCaps.fBGRAIsInternalFormat) {
|
||||
*internalFormat = GR_GL_BGRA;
|
||||
} else {
|
||||
*internalFormat = GR_GL_RGBA;
|
||||
}
|
||||
*type = GR_GL_UNSIGNED_BYTE;
|
||||
*externalType = GR_GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case kRGB_565_GrPixelConfig:
|
||||
*format = GR_GL_RGB;
|
||||
*externalFormat = GR_GL_RGB;
|
||||
*internalFormat = GR_GL_RGB;
|
||||
*type = GR_GL_UNSIGNED_SHORT_5_6_5;
|
||||
*externalType = GR_GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case kRGBA_4444_GrPixelConfig:
|
||||
*format = GR_GL_RGBA;
|
||||
*externalFormat = GR_GL_RGBA;
|
||||
*internalFormat = GR_GL_RGBA;
|
||||
*type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
*externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case kIndex_8_GrPixelConfig:
|
||||
if (this->getCaps().f8BitPaletteSupport) {
|
||||
*format = GR_GL_PALETTE8_RGBA8;
|
||||
*externalFormat = GR_GL_PALETTE8_RGBA8;
|
||||
*internalFormat = GR_GL_PALETTE8_RGBA8;
|
||||
*type = GR_GL_UNSIGNED_BYTE; // unused I think
|
||||
*externalType = GR_GL_UNSIGNED_BYTE; // unused I think
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case kAlpha_8_GrPixelConfig:
|
||||
*format = GR_GL_ALPHA;
|
||||
*externalFormat = GR_GL_ALPHA;
|
||||
*internalFormat = GR_GL_ALPHA;
|
||||
*type = GR_GL_UNSIGNED_BYTE;
|
||||
*externalType = GR_GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -175,6 +175,11 @@ protected:
|
||||
size_t rowBytes,
|
||||
bool invertY) SK_OVERRIDE;
|
||||
|
||||
virtual void onWriteTexturePixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) SK_OVERRIDE;
|
||||
|
||||
virtual void onGpuDrawIndexed(GrPrimitiveType type,
|
||||
uint32_t startVertex,
|
||||
uint32_t startIndex,
|
||||
@ -262,13 +267,14 @@ private:
|
||||
|
||||
bool canBeTexture(GrPixelConfig config,
|
||||
GrGLenum* internalFormat,
|
||||
GrGLenum* format,
|
||||
GrGLenum* type);
|
||||
// helpers for onCreateTexture
|
||||
void allocateAndUploadTexData(const GrGLTexture::Desc& desc,
|
||||
GrGLenum internalFormat,
|
||||
const void* data,
|
||||
size_t rowBytes);
|
||||
GrGLenum* externalFormat,
|
||||
GrGLenum* externalType);
|
||||
// helper for onCreateTexture and writeTexturePixels
|
||||
void uploadTexData(const GrGLTexture::Desc& desc,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dataConfig,
|
||||
const void* data,
|
||||
size_t rowBytes);
|
||||
|
||||
bool createRenderTargetObjects(int width, int height,
|
||||
GrGLuint texID,
|
||||
|
@ -14,14 +14,31 @@
|
||||
#include "GrStencilBuffer.h"
|
||||
|
||||
bool GrRenderTarget::readPixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer) {
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes) {
|
||||
// go through context so that all necessary flushing occurs
|
||||
GrContext* context = this->getGpu()->getContext();
|
||||
GrAssert(NULL != context);
|
||||
GrContext* context = this->getContext();
|
||||
if (NULL == context) {
|
||||
return false;
|
||||
}
|
||||
return context->readRenderTargetPixels(this,
|
||||
left, top,
|
||||
left, top,
|
||||
width, height,
|
||||
config, buffer);
|
||||
config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
void GrRenderTarget::writePixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
// go through context so that all necessary flushing occurs
|
||||
GrContext* context = this->getContext();
|
||||
if (NULL == context) {
|
||||
return;
|
||||
}
|
||||
context->writeRenderTargetPixels(this,
|
||||
left, top,
|
||||
width, height,
|
||||
config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
size_t GrRenderTarget::sizeInBytes() const {
|
||||
|
@ -14,14 +14,31 @@
|
||||
#include "GrRenderTarget.h"
|
||||
|
||||
bool GrTexture::readPixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer) {
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes) {
|
||||
// go through context so that all necessary flushing occurs
|
||||
GrContext* context = this->getGpu()->getContext();
|
||||
GrAssert(NULL != context);
|
||||
GrContext* context = this->getContext();
|
||||
if (NULL == context) {
|
||||
return false;
|
||||
}
|
||||
return context->readTexturePixels(this,
|
||||
left, top,
|
||||
width, height,
|
||||
config, buffer);
|
||||
left, top,
|
||||
width, height,
|
||||
config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
void GrTexture::writePixels(int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
// go through context so that all necessary flushing occurs
|
||||
GrContext* context = this->getContext();
|
||||
if (NULL == context) {
|
||||
return;
|
||||
}
|
||||
context->writeTexturePixels(this,
|
||||
left, top,
|
||||
width, height,
|
||||
config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
void GrTexture::releaseRenderTarget() {
|
||||
|
@ -314,13 +314,8 @@ void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y,
|
||||
bitmap.isOpaque());
|
||||
}
|
||||
|
||||
fContext->setRenderTarget(fRenderTarget);
|
||||
// we aren't setting the clip or matrix, so mark as dirty
|
||||
// we don't need to set them for this call and don't have them anyway
|
||||
fNeedPrepareRenderTarget = true;
|
||||
|
||||
fContext->writePixels(x, y, bitmap.width(), bitmap.height(),
|
||||
config, bitmap.getPixels(), bitmap.rowBytes());
|
||||
fRenderTarget->writePixels(x, y, bitmap.width(), bitmap.height(),
|
||||
config, bitmap.getPixels(), bitmap.rowBytes());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -1031,7 +1026,7 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
|
||||
if (NULL == texture) {
|
||||
return false;
|
||||
}
|
||||
texture->uploadTextureData(0, 0, desc.fWidth, desc.fHeight,
|
||||
texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
|
||||
dstM.fImage, dstM.fRowBytes);
|
||||
|
||||
if (grp->hasTextureOrMask() && ivm.invert(&ivm)) {
|
||||
|
@ -99,8 +99,9 @@ GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx,
|
||||
} else {
|
||||
entry = ctx->lockScratchTexture(desc,
|
||||
GrContext::kExact_ScratchTexMatch);
|
||||
entry.texture()->uploadTextureData(0, 0, bitmap->width(),
|
||||
bitmap->height(), storage.get(), 0);
|
||||
entry.texture()->writePixels(0, 0, bitmap->width(),
|
||||
bitmap->height(), desc.fConfig,
|
||||
storage.get(), 0);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -119,8 +120,11 @@ GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx,
|
||||
} else {
|
||||
entry = ctx->lockScratchTexture(desc,
|
||||
GrContext::kExact_ScratchTexMatch);
|
||||
entry.texture()->uploadTextureData(0, 0, bitmap->width(),
|
||||
bitmap->height(), bitmap->getPixels(), bitmap->rowBytes());
|
||||
entry.texture()->writePixels(0, 0,
|
||||
bitmap->width(), bitmap->height(),
|
||||
desc.fConfig,
|
||||
bitmap->getPixels(),
|
||||
bitmap->rowBytes());
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
|
||||
void* buffer = dst->getPixels();
|
||||
return fTexture->readPixels(left, top, width, height,
|
||||
kSkia8888_PM_GrPixelConfig,
|
||||
buffer);
|
||||
buffer, dst->rowBytes());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -123,7 +123,7 @@ bool SkGrRenderTargetPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset
|
||||
void* buffer = dst->getPixels();
|
||||
return fRenderTarget->readPixels(left, top, width, height,
|
||||
kSkia8888_PM_GrPixelConfig,
|
||||
buffer);
|
||||
buffer, dst->rowBytes());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user