Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index f5c646c86fb636161350ae4d28c98096bf7778e7..039f98f573f1782be0078db02b3edf5d406e9a32 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -593,11 +593,8 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, |
return true; |
} |
-bool GrGLGpu::onWritePixels(GrSurface* surface, |
- int left, int top, int width, int height, |
- GrPixelConfig config, const void* buffer, |
- size_t rowBytes) { |
- GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
+static bool check_write_and_transfer_input(GrGLTexture* glTex, GrSurface* surface, |
+ GrPixelConfig config) { |
if (!glTex) { |
return false; |
} |
@@ -607,11 +604,24 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, |
return false; |
} |
- // Write pixels is only implemented for TEXTURE_2D textures |
+ // Write or transfer of pixels is only implemented for TEXTURE_2D textures |
if (GR_GL_TEXTURE_2D != glTex->target()) { |
return false; |
} |
+ return true; |
+} |
+ |
+bool GrGLGpu::onWritePixels(GrSurface* surface, |
+ int left, int top, int width, int height, |
+ GrPixelConfig config, const void* buffer, |
+ size_t rowBytes) { |
+ GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
+ |
+ if (!check_write_and_transfer_input(glTex, surface, config)) { |
+ return false; |
+ } |
+ |
this->setScratchTextureUnit(); |
GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
@@ -619,11 +629,11 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, |
if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
// We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixels() |
SkASSERT(config == glTex->desc().fConfig); |
- success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), buffer, false, left, |
- top, width, height); |
+ success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), buffer, |
+ kWrite_UploadType, left, top, width, height); |
} else { |
- success = this->uploadTexData(glTex->desc(), glTex->target(), false, left, top, width, |
- height, config, buffer, rowBytes); |
+ success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_UploadType, |
+ left, top, width, height, config, buffer, rowBytes); |
} |
if (success) { |
@@ -634,6 +644,43 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, |
return false; |
} |
+bool GrGLGpu::onTransferPixels(GrSurface* surface, |
+ int left, int top, int width, int height, |
+ GrPixelConfig config, GrTransferBuffer* buffer, |
+ size_t offset, size_t rowBytes) { |
+ GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
+ |
+ if (!check_write_and_transfer_input(glTex, surface, config)) { |
+ return false; |
+ } |
+ |
+ // For the moment, can't transfer compressed data |
+ if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
+ return false; |
+ } |
+ |
+ this->setScratchTextureUnit(); |
+ GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
+ |
+ SkASSERT(!buffer->isMapped()); |
+ GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer); |
+ // bind the transfer buffer |
+ SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || |
+ GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType()); |
+ GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); |
+ |
+ bool success = false; |
+ success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_UploadType, |
+ left, top, width, height, config, buffer, rowBytes); |
+ |
+ if (success) { |
+ glTex->texturePriv().dirtyMipMaps(true); |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
// For GL_[UN]PACK_ALIGNMENT. |
static inline GrGLint config_alignment(GrPixelConfig config) { |
SkASSERT(!GrPixelConfigIsCompressed(config)); |
@@ -666,12 +713,13 @@ static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
GrGLenum target, |
- bool isNewTexture, |
+ UploadType uploadType, |
int left, int top, int width, int height, |
GrPixelConfig dataConfig, |
- const void* data, |
+ const void* dataOrOffset, |
size_t rowBytes) { |
- SkASSERT(data || isNewTexture); |
+ SkASSERT(dataOrOffset || kNewTexture_UploadType == uploadType || |
+ kTransfer_UploadType == uploadType); |
// If we're uploading compressed data then we should be using uploadCompressedTexData |
SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); |
@@ -680,7 +728,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
size_t bpp = GrBytesPerPixel(dataConfig); |
if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top, |
- &width, &height, &data, &rowBytes)) { |
+ &width, &height, &dataOrOffset, &rowBytes)) { |
return false; |
} |
size_t trimRowBytes = width * bpp; |
@@ -711,7 +759,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
bool restoreGLRowLength = false; |
bool swFlipY = false; |
bool glFlipY = false; |
- if (data) { |
+ if (dataOrOffset) { |
if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
if (this->glCaps().unpackFlipYSupport()) { |
glFlipY = true; |
@@ -726,11 +774,11 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); |
restoreGLRowLength = true; |
} |
- } else { |
+ } else if (kTransfer_UploadType != uploadType) { |
if (trimRowBytes != rowBytes || swFlipY) { |
// copy data into our new storage, skipping the trailing bytes |
size_t trimSize = height * trimRowBytes; |
- const char* src = (const char*)data; |
+ const char* src = (const char*)dataOrOffset; |
if (swFlipY) { |
src += (height - 1) * rowBytes; |
} |
@@ -745,8 +793,10 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
dst += trimRowBytes; |
} |
// now point data to our copied version |
- data = tempStorage.get(); |
+ dataOrOffset = tempStorage.get(); |
} |
+ } else { |
+ return false; |
} |
if (glFlipY) { |
GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); |
@@ -754,14 +804,15 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(dataConfig))); |
} |
bool succeeded = true; |
- if (isNewTexture) { |
- if (data && !(0 == left && 0 == top && desc.fWidth == width && desc.fHeight == height)) { |
+ if (kNewTexture_UploadType == uploadType) { |
+ if (dataOrOffset && |
+ !(0 == left && 0 == top && desc.fWidth == width && desc.fHeight == height)) { |
succeeded = false; |
} else { |
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
GL_ALLOC_CALL(this->glInterface(), TexImage2D(target, 0, internalFormat, desc.fWidth, |
desc.fHeight, 0, externalFormat, |
- externalType, data)); |
+ externalType, dataOrOffset)); |
GrGLenum error = check_alloc_error(desc, this->glInterface()); |
if (error != GR_GL_NO_ERROR) { |
succeeded = false; |
@@ -775,7 +826,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
0, // level |
left, top, |
width, height, |
- externalFormat, externalType, data)); |
+ externalFormat, externalType, dataOrOffset)); |
} |
if (restoreGLRowLength) { |
@@ -796,10 +847,11 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
GrGLenum target, |
const void* data, |
- bool isNewTexture, |
+ UploadType uploadType, |
int left, int top, int width, int height) { |
SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); |
- SkASSERT(data || isNewTexture); |
+ SkASSERT(kTransfer_UploadType != uploadType && |
+ (data || kNewTexture_UploadType != uploadType)); |
// No support for software flip y, yet... |
SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
@@ -830,7 +882,7 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
// sized vs base internal format distinction for compressed textures. |
GrGLenum internalFormat =this->glCaps().configGLFormats(desc.fConfig).fSizedInternalFormat; |
- if (isNewTexture) { |
+ if (kNewTexture_UploadType == uploadType) { |
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
GL_ALLOC_CALL(this->glInterface(), |
CompressedTexImage2D(target, |
@@ -1076,7 +1128,7 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, |
GL_CALL(TexParameteri(idDesc.fInfo.fTarget, |
GR_GL_TEXTURE_WRAP_T, |
initialTexParams.fWrapT)); |
- if (!this->uploadTexData(desc, idDesc.fInfo.fTarget, true, 0, 0, |
+ if (!this->uploadTexData(desc, idDesc.fInfo.fTarget, kNewTexture_UploadType, 0, 0, |
desc.fWidth, desc.fHeight, |
desc.fConfig, srcData, rowBytes)) { |
GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
@@ -1438,16 +1490,17 @@ GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType xfer |
if (desc.fID) { |
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
// make sure driver can allocate memory for this bmapuffer |
- GrGLenum type; |
+ GrGLenum target; |
if (GrGLCaps::kChromium_TransferBufferType == xferBufferType) { |
- type = toGpu ? GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM |
+ target = toGpu ? GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM |
: GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM; |
} else { |
SkASSERT(GrGLCaps::kPBO_TransferBufferType == xferBufferType); |
- type = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER; |
+ target = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER; |
} |
- GL_ALLOC_CALL(this->glInterface(), |
- BufferData(type, |
+ GL_CALL(BindBuffer(target, desc.fID)); |
+ GL_ALLOC_CALL(this->glInterface(), |
+ BufferData(target, |
(GrGLsizeiptr) desc.fSizeInBytes, |
nullptr, // data ptr |
(toGpu ? GR_GL_STREAM_DRAW : GR_GL_STREAM_READ))); |
@@ -1455,7 +1508,7 @@ GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType xfer |
GL_CALL(DeleteBuffers(1, &desc.fID)); |
return nullptr; |
} |
- GrTransferBuffer* transferBuffer = new GrGLTransferBuffer(this, desc, type); |
+ GrTransferBuffer* transferBuffer = new GrGLTransferBuffer(this, desc, target); |
return transferBuffer; |
} |
@@ -1655,11 +1708,14 @@ void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage |
if (currentSize != requestedSize) { |
GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); |
} |
- static const GrGLbitfield kWriteAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT | |
- GR_GL_MAP_WRITE_BIT; |
+ GrGLbitfield writeAccess = GR_GL_MAP_WRITE_BIT; |
+ // TODO: allow the client to specify invalidation in the stream draw case |
+ if (GrGLBufferImpl::kStreamDraw_Usage != usage) { |
+ writeAccess |= GR_GL_MAP_INVALIDATE_BUFFER_BIT; |
+ } |
GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, readOnly ? |
GR_GL_MAP_READ_BIT : |
- kWriteAccess)); |
+ writeAccess)); |
break; |
} |
case GrGLCaps::kChromium_MapBufferType: |