Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Unified Diff: src/gpu/gl/GrGLGpu.cpp

Issue 1249543003: Creating functions for uploading a mipmapped texture. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Fixing merge mistakes Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/gpu/gl/GrGLGpu.cpp
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index cb12fefc3291f48388275702a71e48d555ddd408..83785e2117b85f17dbef22041657bb302bca4b3f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -5,7 +5,6 @@
* found in the LICENSE file.
*/
-
#include "GrGLGpu.h"
#include "GrGLGLSL.h"
#include "GrGLStencilAttachment.h"
@@ -21,6 +20,7 @@
#include "glsl/GrGLSLCaps.h"
#include "SkStrokeRec.h"
#include "SkTemplates.h"
+#include "SkTypes.h"
#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
@@ -426,7 +426,9 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
GrSurfaceDesc surfDesc;
idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
-
+ // We only support GL_TEXTURE_2D at the moment.
+ idDesc.fTarget = GR_GL_TEXTURE_2D;
+
switch (ownership) {
case kAdopt_GrWrapOwnership:
idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
@@ -434,7 +436,7 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
case kBorrow_GrWrapOwnership:
idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
break;
- }
+ }
// next line relies on GrBackendTextureDesc's flags matching GrTexture's
surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
@@ -457,7 +459,7 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
if (renderTarget) {
GrGLRenderTarget::IDDesc rtIDDesc;
if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
- idDesc.fTextureID, &rtIDDesc)) {
+ idDesc.fTextureID, idDesc.fTarget, &rtIDDesc)) {
return nullptr;
}
texture = new GrGLTextureRenderTarget(this, surfDesc, idDesc, rtIDDesc);
@@ -484,7 +486,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
case kBorrow_GrWrapOwnership:
idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
break;
- }
+ }
idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig;
GrSurfaceDesc desc;
@@ -500,7 +502,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
////////////////////////////////////////////////////////////////////////////////
bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
- size_t rowBytes, GrPixelConfig srcConfig,
+ GrPixelConfig srcConfig,
DrawPreference* drawPreference,
WritePixelTempDrawInfo* tempDrawInfo) {
if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
@@ -560,8 +562,8 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
bool GrGLGpu::onWritePixels(GrSurface* surface,
int left, int top, int width, int height,
- GrPixelConfig config, const void* buffer,
- size_t rowBytes) {
+ GrPixelConfig config,
+ const SkTArray<SkMipMapLevel>& texels) {
GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
if (!glTex) {
return false;
@@ -573,25 +575,20 @@ bool GrGLGpu::onWritePixels(GrSurface* surface,
}
this->setScratchTextureUnit();
- GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID()));
+ GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
bool success = false;
if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) {
// We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixels()
SkASSERT(config == glTex->desc().fConfig);
- success = this->uploadCompressedTexData(glTex->desc(), buffer, false, left, top, width,
- height);
+ success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), texels, false,
+ left, top, width, height);
} else {
- success = this->uploadTexData(glTex->desc(), false, left, top, width, height, config,
- buffer, rowBytes);
+ success = this->uploadTexData(glTex->desc(), glTex->target(), false, left, top, width,
+ height, config, texels);
}
- if (success) {
- glTex->texturePriv().dirtyMipMaps(true);
- return true;
- }
-
- return false;
+ return success;
}
static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc,
@@ -603,36 +600,17 @@ static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc,
}
}
-bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
- bool isNewTexture,
- int left, int top, int width, int height,
- GrPixelConfig dataConfig,
- const void* data,
- size_t rowBytes) {
- SkASSERT(data || isNewTexture);
-
- // If we're uploading compressed data then we should be using uploadCompressedTexData
- SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
-
- size_t bpp = GrBytesPerPixel(dataConfig);
- if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
- &width, &height, &data, &rowBytes)) {
- return false;
- }
- size_t trimRowBytes = width * bpp;
-
- // in case we need a temporary, trimmed copy of the src pixels
- SkAutoSMalloc<128 * 128> tempStorage;
-
- // We currently lazily create MIPMAPs when the we see a draw with
- // GrTextureParams::kMipMap_FilterMode. Using texture storage requires that the
- // MIP levels are all created when the texture is created. So for now we don't use
- // texture storage.
- bool useTexStorage = false &&
- isNewTexture &&
- this->glCaps().texStorageSupport();
-
- if (useTexStorage && kGL_GrGLStandard == this->glStandard()) {
+/**
+ * Determines if TexStorage can be used when creating a texture.
+ *
+ * @param caps The capabilities of the GL device.
+ * @param standard The GL standard in use.
+ * @param desc The surface descriptor for the texture being created.
+ */
+static bool can_use_tex_storage(const GrGLCaps& caps, const GrGLStandard& standard,
+ const GrSurfaceDesc& desc) {
+ bool useTexStorage = caps.texStorageSupport();
+ if (useTexStorage && kGL_GrGLStandard == standard) {
// 565 is not a sized internal format on desktop GL. So on desktop with
// 565 we always use an unsized internal format to let the system pick
// the best sized format to convert the 565 data to. Since TexStorage
@@ -640,59 +618,92 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig;
}
- GrGLenum internalFormat = 0x0; // suppress warning
- GrGLenum externalFormat = 0x0; // suppress warning
- GrGLenum externalType = 0x0; // suppress warning
+ return useTexStorage;
+}
+/**
+ * Determines if sized internal formats are available for the texture being created.
+ *
+ * @param useTexStorage The result of a call to can_use_tex_storage().
+ * @param caps The capabilities of the GL device.
+ * @param standard The GL standard in use.
+ * @param version The GL version in use.
+ * @param dataConfig The pixel configuration for the texture being created.
+ */
+static bool can_use_sized_format(bool useTexStorage, const GrGLCaps& caps,
+ const GrGLStandard& standard, const GrGLVersion& version,
+ GrPixelConfig dataConfig) {
// glTexStorage requires sized internal formats on both desktop and ES. ES2 requires an unsized
// format for glTexImage, unlike ES3 and desktop.
bool useSizedFormat = useTexStorage;
- if (kGL_GrGLStandard == this->glStandard() ||
- (this->glVersion() >= GR_GL_VER(3, 0) &&
+ if (kGL_GrGLStandard == standard ||
+ (version >= GR_GL_VER(3, 0) &&
// ES3 only works with sized BGRA8 format if "GL_APPLE_texture_format_BGRA8888" enabled
- (kBGRA_8888_GrPixelConfig != dataConfig || !this->glCaps().bgraIsInternalFormat()))) {
+ (kBGRA_8888_GrPixelConfig != dataConfig || !caps.bgraIsInternalFormat()))) {
useSizedFormat = true;
}
- if (!this->configToGLFormats(dataConfig, useSizedFormat, &internalFormat,
- &externalFormat, &externalType)) {
- return false;
- }
+ return useSizedFormat;
+}
- /*
- * 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 swFlipY = false;
- bool glFlipY = false;
- if (data) {
- if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
- if (this->glCaps().unpackFlipYSupport()) {
- glFlipY = true;
- } else {
- swFlipY = true;
- }
+/**
+ * Prior to a texture being created, the image may need to be flipped vertically. This function
+ * prepares the texels for texture creation.
+ *
+ * @param desc The surface descriptor for the texture being created.
+ * @param caps The capabilities of the GL device.
+ * @param interface The GL interface in use.
+ * @param swFlipY Should software be used when flipping a texture vertically?
+ * @param glFlipY Should GL be used when flipping a texture vertically?
+ * @param width The width of the texture in texels.
+ * @param height The height of the texture in texels.
+ * @param bpp The bits per pixel (or texel, really) of the texture.
+ * @param texels An array of mipmap levels which contain the texel data at that level.
+ * @param tempStorage In the case where the image needs to be flipped vertically, it will
+ * use tempStorage as a buffer.
+ * @param restoreGLRowLength After the texture is created, will the GL row length unpacking need
+ * to be restored?
+ */
+static void prepare_image_for_writing_to_texture(const GrSurfaceDesc& desc, const GrGLCaps& caps,
+ const GrGLInterface& interface, bool swFlipY,
+ bool glFlipY, int bpp,
+ SkTArray<SkMipMapLevel>& texels,
+ SkAutoSMalloc<128 * 128>& tempStorage,
+ bool* restoreGLRowLength) {
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ if (texels[currentMipLevel].fTexels == nullptr) {
+ continue;
}
- if (this->glCaps().unpackRowLengthSupport() && !swFlipY) {
+
+ const size_t trimRowBytes = texels[currentMipLevel].fWidth * bpp;
+
+ /*
+ * 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.
+ */
+ *restoreGLRowLength = false;
+
+ const size_t rowBytes = texels[currentMipLevel].fRowBytes;
+ if (caps.unpackRowLengthSupport() && !swFlipY) {
// 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;
+ GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
+ *restoreGLRowLength = true;
}
} else {
if (trimRowBytes != rowBytes || swFlipY) {
+ const uint32_t height = texels[currentMipLevel].fHeight;
// copy data into our new storage, skipping the trailing bytes
- size_t trimSize = height * trimRowBytes;
- const char* src = (const char*)data;
- if (swFlipY) {
+ const size_t trimSize = height * trimRowBytes;
+ const char* src = (const char*)texels[currentMipLevel].fTexels;
+ if (swFlipY && height >= 1) {
src += (height - 1) * rowBytes;
}
char* dst = (char*)tempStorage.reset(trimSize);
- for (int y = 0; y < height; y++) {
+ for (uint32_t y = 0; y < height; y++) {
memcpy(dst, src, trimRowBytes);
if (swFlipY) {
src -= rowBytes;
@@ -702,70 +713,291 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
dst += trimRowBytes;
}
// now point data to our copied version
- data = tempStorage.get();
+ texels[currentMipLevel] = SkMipMapLevel(tempStorage.get(), trimRowBytes,
+ texels[currentMipLevel].fWidth,
+ texels[currentMipLevel].fHeight);
}
}
if (glFlipY) {
- GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
+ GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
}
- GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT,
- static_cast<GrGLint>(GrUnpackAlignment(dataConfig))));
+ GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT,
+ static_cast<GrGLint>(GrUnpackAlignment(desc.fConfig))));
}
- bool succeeded = true;
- if (isNewTexture &&
- 0 == left && 0 == top &&
- desc.fWidth == width && desc.fHeight == height) {
- CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
- if (useTexStorage) {
- // We never resize or change formats of textures.
- GL_ALLOC_CALL(this->glInterface(),
- TexStorage2D(GR_GL_TEXTURE_2D,
- 1, // levels
- internalFormat,
- desc.fWidth, desc.fHeight));
+}
+
+/**
+ * Creates storage space for the texture and fills it with texels.
+ *
+ * @param desc The surface descriptor for the texture being created.
+ * @param interface The GL interface in use.
+ * @param useTexStorage The result of a call to can_use_tex_storage().
+ * @param internalFormat The data format used for the internal storage of the texture.
+ * @param externalFormat The data format used for the external storage of the texture.
+ * @param externalType The type of the data used for the external storage of the texture.
+ * @param texels The texel data of the texture being created.
+ * @param succeeded Set to true if allocating and populating the texture completed
+ * without error.
+ */
+static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc,
+ const GrGLInterface& interface,
+ GrGLenum target,
+ bool useTexStorage,
+ GrGLenum internalFormat,
+ GrGLenum externalFormat,
+ GrGLenum externalType,
+ const SkTArray<SkMipMapLevel>& texels,
+ bool* succeeded) {
+ CLEAR_ERROR_BEFORE_ALLOC(&interface);
+ if (useTexStorage) {
+ // We never resize or change formats of textures.
+ GL_ALLOC_CALL(&interface,
+ TexStorage2D(target,
+ texels.count(),
+ internalFormat,
+ desc.fWidth, desc.fHeight));
+
+ GrGLenum error = check_alloc_error(desc, &interface);
+ if (error != GR_GL_NO_ERROR) {
+ *succeeded = false;
} else {
- GL_ALLOC_CALL(this->glInterface(),
- TexImage2D(GR_GL_TEXTURE_2D,
- 0, // level
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ const void* currentMipData = texels[currentMipLevel].fTexels;
+ if (currentMipData == nullptr) {
+ continue;
+ }
+
+ GR_GL_CALL(&interface,
+ TexSubImage2D(GR_GL_TEXTURE_2D,
+ currentMipLevel,
+ 0, // left
+ 0, // top
+ texels[currentMipLevel].fWidth,
+ texels[currentMipLevel].fHeight,
+ externalFormat, externalType,
+ currentMipData));
+ }
+ *succeeded = true;
+ }
+ } else {
+ *succeeded = true;
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ GL_ALLOC_CALL(&interface,
+ TexImage2D(target,
+ currentMipLevel,
internalFormat,
- desc.fWidth, desc.fHeight,
+ texels[currentMipLevel].fWidth,
+ texels[currentMipLevel].fHeight,
0, // border
externalFormat, externalType,
- data));
+ texels[currentMipLevel].fTexels));
+ GrGLenum error = check_alloc_error(desc, &interface);
+ if (error != GR_GL_NO_ERROR) {
+ *succeeded = false;
+ break;
+ }
}
- GrGLenum error = check_alloc_error(desc, this->glInterface());
+ }
+}
+
+/**
+ * Creates storage space for the texture and fills it with texels.
+ *
+ * @param desc The surface descriptor for the texture being created.
+ * @param interface The GL interface in use.
+ * @param useTexStorage The result of a call to can_use_tex_storage().
+ * @param internalFormat The data format used for the internal storage of the texture.
+ * @param texels The texel data of the texture being created.
+ */
+static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc,
+ const GrGLInterface& interface,
+ GrGLenum target,
+ bool useTexStorage, GrGLenum internalFormat,
+ const SkTArray<SkMipMapLevel>& texels) {
+ CLEAR_ERROR_BEFORE_ALLOC(&interface);
+ if (useTexStorage) {
+ // We never resize or change formats of textures.
+ GL_ALLOC_CALL(&interface,
+ TexStorage2D(target,
+ texels.count(),
+ internalFormat,
+ desc.fWidth, desc.fHeight));
+ GrGLenum error = check_alloc_error(desc, &interface);
if (error != GR_GL_NO_ERROR) {
- succeeded = false;
+ return false;
} else {
- // if we have data and we used TexStorage to create the texture, we
- // now upload with TexSubImage.
- if (data && useTexStorage) {
- GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
- 0, // level
- left, top,
- width, height,
- externalFormat, externalType,
- data));
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ const void* currentMipData = texels[currentMipLevel].fTexels;
+ if (currentMipData == nullptr) {
+ continue;
+ }
+
+ const uint32_t width = texels[currentMipLevel].fWidth;
+ const uint32_t height = texels[currentMipLevel].fHeight;
+
+ // Make sure that the width and height that we pass to OpenGL
+ // is a multiple of the block size.
+ size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
+ GR_GL_CALL(&interface, CompressedTexSubImage2D(GR_GL_TEXTURE_2D,
+ currentMipLevel,
+ 0, // left
+ 0, // top
+ width, height,
+ internalFormat, SkToInt(dataSize),
+ currentMipData));
}
}
} else {
- if (swFlipY || glFlipY) {
- top = desc.fHeight - (top + height);
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ const uint32_t width = texels[currentMipLevel].fWidth;
+ const uint32_t height = texels[currentMipLevel].fHeight;
+
+ // Make sure that the width and height that we pass to OpenGL
+ // is a multiple of the block size.
+ size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
+
+ GL_ALLOC_CALL(&interface,
+ CompressedTexImage2D(target,
+ texels.count(),
+ internalFormat,
+ width, height,
+ 0, // border
+ SkToInt(dataSize),
+ texels[currentMipLevel].fTexels));
+
+ GrGLenum error = check_alloc_error(desc, &interface);
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ }
}
- GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
- 0, // level
- left, top,
- width, height,
- externalFormat, externalType, data));
}
+ return true;
+}
+/**
+ * After a texture is created, any state which was altered during its creation
+ * needs to be restored.
+ *
+ * @param interface The GL interface to use.
+ * @param caps The capabilities of the GL device.
+ * @param restoreGLRowLength Should the row length unpacking be restored?
+ * @param glFlipY Did GL flip the texture vertically?
+ */
+static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLCaps& caps,
+ bool restoreGLRowLength, bool glFlipY) {
if (restoreGLRowLength) {
- SkASSERT(this->glCaps().unpackRowLengthSupport());
- GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
+ SkASSERT(caps.unpackRowLengthSupport());
+ GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
}
if (glFlipY) {
- GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
+ GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
}
+}
+
+bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
+ GrGLenum target,
+ bool isNewTexture,
+ int left, int top, int width, int height,
+ GrPixelConfig dataConfig,
+ const SkTArray<SkMipMapLevel>& texels) {
+ // If we're uploading compressed data then we should be using uploadCompressedTexData
+ SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
+
+ SkTArray<SkMipMapLevel> texelsCopy(texels);
+
+ for (int currentMipLevel = texelsCopy.count() - 1; currentMipLevel >= 0; currentMipLevel--) {
+ //SkASSERT(texelsCopy[currentMipLevel].fTexels || isNewTexture);
+ }
+
+
+ const GrGLInterface* interface = this->glInterface();
+ const GrGLCaps& caps = this->glCaps();
+ GrGLStandard standard = this->glStandard();
+ GrGLVersion version = this->glVersion();
+
+ size_t bpp = GrBytesPerPixel(dataConfig);
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ if (texelsCopy[currentMipLevel].fTexels == nullptr) {
+ continue;
+ }
+
+ if (texelsCopy[currentMipLevel].fHeight > SK_MaxS32
+ || texelsCopy[currentMipLevel].fWidth > SK_MaxS32) {
+ return false;
+ }
+ int currentMipHeight = texelsCopy[currentMipLevel].fHeight;
+ int currentMipWidth = texelsCopy[currentMipLevel].fWidth;
+ if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
+ &currentMipWidth,
+ &currentMipHeight,
+ &texelsCopy[currentMipLevel].fTexels,
+ &texelsCopy[currentMipLevel].fRowBytes)) {
+ return false;
+ }
+ if (currentMipWidth < 0 || currentMipHeight < 0) {
+ return false;
+ }
+ texelsCopy[currentMipLevel].fWidth = currentMipWidth;
+ texelsCopy[currentMipLevel].fHeight = currentMipHeight;
+ }
+
+ bool useTexStorage = can_use_tex_storage(caps, standard, desc);
+ bool useSizedFormat = can_use_sized_format(useTexStorage, caps, standard, version, dataConfig);
+
+ GrGLenum internalFormat = 0x0; // suppress warning
+ GrGLenum externalFormat = 0x0; // suppress warning
+ GrGLenum externalType = 0x0; // suppress warning
+
+ if (!this->configToGLFormats(dataConfig, useSizedFormat, &internalFormat,
+ &externalFormat, &externalType)) {
+ return false;
+ }
+
+ bool swFlipY = false;
+ bool glFlipY = false;
+
+ if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
+ if (caps.unpackFlipYSupport()) {
+ glFlipY = true;
+ } else {
+ swFlipY = true;
+ }
+ }
+
+ bool restoreGLRowLength = false;
+
+ // in case we need a temporary, trimmed copy of the src pixels
+ SkAutoSMalloc<128 * 128> tempStorage;
+ prepare_image_for_writing_to_texture(desc, caps, *interface, swFlipY, glFlipY, bpp, texelsCopy,
+ tempStorage, &restoreGLRowLength);
+ bool succeeded = true;
+ if (isNewTexture &&
+ 0 == left && 0 == top &&
+ desc.fWidth == width && desc.fHeight == height) {
+ allocate_and_populate_uncompressed_texture(desc, *interface, useTexStorage, internalFormat,
+ externalFormat, externalType, target,
+ texelsCopy, &succeeded);
+ } else {
+ if (swFlipY || glFlipY) {
+ top = desc.fHeight - (top + height);
+ }
+ for (int currentMipLevel = 0; currentMipLevel < texelsCopy.count(); currentMipLevel++) {
+ if (texelsCopy[currentMipLevel].fTexels == nullptr) {
+ continue;
+ }
+
+ GL_CALL(TexSubImage2D(target,
+ currentMipLevel,
+ left, top,
+ texelsCopy[currentMipLevel].fWidth,
+ texelsCopy[currentMipLevel].fHeight,
+ externalFormat, externalType,
+ texelsCopy[currentMipLevel].fTexels));
+ }
+ }
+
+ restore_pixelstore_state(*interface, caps, restoreGLRowLength, glFlipY);
+
return succeeded;
}
@@ -775,14 +1007,19 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
// the proper upload semantics. Then users can construct this function how they
// see fit if they want to go against the "standard" way to do it.
bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
- const void* data,
+ GrGLenum target,
+ const SkTArray<SkMipMapLevel>& texels,
bool isNewTexture,
int left, int top, int width, int height) {
- SkASSERT(data || isNewTexture);
+ SkASSERT(isNewTexture);
// No support for software flip y, yet...
SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin);
+ const GrGLInterface* interface = this->glInterface();
+ const GrGLCaps& caps = this->glCaps();
+ GrGLStandard standard = this->glStandard();
+
if (-1 == width) {
width = desc.fWidth;
}
@@ -801,9 +1038,7 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
}
#endif
- // Make sure that the width and height that we pass to OpenGL
- // is a multiple of the block size.
- size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
+ bool useTexStorage = can_use_tex_storage(caps, standard, desc);
// We only need the internal format for compressed 2D textures.
GrGLenum internalFormat = 0;
@@ -812,31 +1047,32 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
}
if (isNewTexture) {
- CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
- GL_ALLOC_CALL(this->glInterface(),
- CompressedTexImage2D(GR_GL_TEXTURE_2D,
- 0, // level
- internalFormat,
- width, height,
- 0, // border
- SkToInt(dataSize),
- data));
- GrGLenum error = check_alloc_error(desc, this->glInterface());
- if (error != GR_GL_NO_ERROR) {
- return false;
- }
+ return allocate_and_populate_compressed_texture(desc, *interface, target, useTexStorage,
+ internalFormat, texels);
} else {
// Paletted textures can't be updated.
if (GR_GL_PALETTE8_RGBA8 == internalFormat) {
return false;
}
- GL_CALL(CompressedTexSubImage2D(GR_GL_TEXTURE_2D,
- 0, // level
- left, top,
- width, height,
- internalFormat,
- SkToInt(dataSize),
- data));
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ if (texels[currentMipLevel].fTexels == nullptr) {
+ continue;
+ }
+
+ // Make sure that the width and height that we pass to OpenGL
+ // is a multiple of the block size.
+ size_t dataSize = GrCompressedFormatDataSize(desc.fConfig,
+ texels[currentMipLevel].fWidth,
+ texels[currentMipLevel].fHeight);
+ GL_CALL(CompressedTexSubImage2D(target,
+ currentMipLevel,
+ left, top,
+ texels[currentMipLevel].fWidth,
+ texels[currentMipLevel].fHeight,
+ internalFormat,
+ dataSize,
+ texels[currentMipLevel].fTexels));
+ }
}
return true;
@@ -884,6 +1120,7 @@ static bool renderbuffer_storage_msaa(const GrGLContext& ctx,
bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
GrGpuResource::LifeCycle lifeCycle,
GrGLuint texID,
+ GrGLenum textureTarget,
GrGLRenderTarget::IDDesc* idDesc) {
idDesc->fMSColorRenderbufferID = 0;
idDesc->fRTFBOID = 0;
@@ -942,9 +1179,9 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
fStats.incRenderTargetBinds();
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID));
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_COLOR_ATTACHMENT0,
- GR_GL_RENDERBUFFER,
- idDesc->fMSColorRenderbufferID));
+ GR_GL_COLOR_ATTACHMENT0,
+ GR_GL_RENDERBUFFER,
+ idDesc->fMSColorRenderbufferID));
if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
!this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
@@ -960,12 +1197,12 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 0) {
GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
- GR_GL_TEXTURE_2D,
+ textureTarget,
texID, 0, desc.fSampleCnt));
} else {
GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
- GR_GL_TEXTURE_2D,
+ textureTarget,
texID, 0));
}
if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
@@ -1004,9 +1241,46 @@ static size_t as_size_t(int x) {
}
#endif
+static GrGLTexture::IDDesc generate_and_bind_gl_texture(const GrGLInterface* interface,
+ GrGpuResource::LifeCycle lifeCycle) {
+ GrGLTexture::IDDesc idDesc;
+ GR_GL_CALL(interface, GenTextures(1, &idDesc.fTextureID));
+ idDesc.fLifeCycle = lifeCycle;
+ // We only support GL_TEXTURE_2D at the moment.
+ idDesc.fTarget = GR_GL_TEXTURE_2D;
+ return idDesc;
+}
+
+static GrGLTexture::TexParams set_initial_texture_params(const GrGLInterface* interface,
+ GrGLTexture::IDDesc idDesc) {
+ // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
+ // drivers have a bug where an FBO won't be complete if it includes a
+ // texture that is not mipmap complete (considering the filter in use).
+ GrGLTexture::TexParams initialTexParams;
+ // we only set a subset here so invalidate first
+ initialTexParams.invalidate();
+ initialTexParams.fMinFilter = GR_GL_NEAREST;
+ initialTexParams.fMagFilter = GR_GL_NEAREST;
+ initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE;
+ initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE;
+ GR_GL_CALL(interface, TexParameteri(idDesc.fTarget,
+ GR_GL_TEXTURE_MAG_FILTER,
+ initialTexParams.fMagFilter));
+ GR_GL_CALL(interface, TexParameteri(idDesc.fTarget,
+ GR_GL_TEXTURE_MIN_FILTER,
+ initialTexParams.fMinFilter));
+ GR_GL_CALL(interface, TexParameteri(idDesc.fTarget,
+ GR_GL_TEXTURE_WRAP_S,
+ initialTexParams.fWrapS));
+ GR_GL_CALL(interface, TexParameteri(idDesc.fTarget,
+ GR_GL_TEXTURE_WRAP_T,
+ initialTexParams.fWrapT));
+ return initialTexParams;
+}
+
GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
GrGpuResource::LifeCycle lifeCycle,
- const void* srcData, size_t rowBytes) {
+ const SkTArray<SkMipMapLevel>& texels) {
// We fail if the MSAA was requested and is not available.
if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
//SkDebugf("MSAA RT requested but not supported on this platform.");
@@ -1015,49 +1289,27 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
- GrGLTexture::IDDesc idDesc;
- GL_CALL(GenTextures(1, &idDesc.fTextureID));
- idDesc.fLifeCycle = lifeCycle;
-
+ GrGLTexture::IDDesc idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle);
if (!idDesc.fTextureID) {
return return_null_texture();
}
this->setScratchTextureUnit();
- GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID));
+ GL_CALL(BindTexture(idDesc.fTarget, idDesc.fTextureID));
if (renderTarget && this->glCaps().textureUsageSupport()) {
// provides a hint about how this texture will be used
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GL_CALL(TexParameteri(idDesc.fTarget,
GR_GL_TEXTURE_USAGE,
GR_GL_FRAMEBUFFER_ATTACHMENT));
}
- // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
- // drivers have a bug where an FBO won't be complete if it includes a
- // texture that is not mipmap complete (considering the filter in use).
- GrGLTexture::TexParams initialTexParams;
- // we only set a subset here so invalidate first
- initialTexParams.invalidate();
- initialTexParams.fMinFilter = GR_GL_NEAREST;
- initialTexParams.fMagFilter = GR_GL_NEAREST;
- initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE;
- initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE;
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MAG_FILTER,
- initialTexParams.fMagFilter));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MIN_FILTER,
- initialTexParams.fMinFilter));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_S,
- initialTexParams.fWrapS));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_T,
- initialTexParams.fWrapT));
- if (!this->uploadTexData(desc, true, 0, 0,
+ GrGLTexture::TexParams initialTexParams = set_initial_texture_params(this->glInterface(),
+ idDesc);
+
+ if (!this->uploadTexData(desc, GR_GL_TEXTURE_2D, true, 0, 0,
desc.fWidth, desc.fHeight,
- desc.fConfig, srcData, rowBytes)) {
+ desc.fConfig, texels)) {
GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
return return_null_texture();
}
@@ -1065,10 +1317,11 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
GrGLTexture* tex;
if (renderTarget) {
// unbind the texture from the texture unit before binding it to the frame buffer
- GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
+ GL_CALL(BindTexture(idDesc.fTarget, 0));
GrGLRenderTarget::IDDesc rtIDDesc;
- if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fTextureID, &rtIDDesc)) {
+ if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fTextureID, idDesc.fTarget,
+ &rtIDDesc)) {
GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
return return_null_texture();
}
@@ -1086,47 +1339,24 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
GrGpuResource::LifeCycle lifeCycle,
- const void* srcData) {
+ const SkTArray<SkMipMapLevel>& texels) {
// Make sure that we're not flipping Y.
if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
return return_null_texture();
}
- GrGLTexture::IDDesc idDesc;
- GL_CALL(GenTextures(1, &idDesc.fTextureID));
- idDesc.fLifeCycle = lifeCycle;
-
+ GrGLTexture::IDDesc idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle);
if (!idDesc.fTextureID) {
return return_null_texture();
}
this->setScratchTextureUnit();
- GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID));
+ GL_CALL(BindTexture(idDesc.fTarget, idDesc.fTextureID));
- // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
- // drivers have a bug where an FBO won't be complete if it includes a
- // texture that is not mipmap complete (considering the filter in use).
- GrGLTexture::TexParams initialTexParams;
- // we only set a subset here so invalidate first
- initialTexParams.invalidate();
- initialTexParams.fMinFilter = GR_GL_NEAREST;
- initialTexParams.fMagFilter = GR_GL_NEAREST;
- initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE;
- initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE;
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MAG_FILTER,
- initialTexParams.fMagFilter));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MIN_FILTER,
- initialTexParams.fMinFilter));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_S,
- initialTexParams.fWrapS));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_T,
- initialTexParams.fWrapT));
-
- if (!this->uploadCompressedTexData(desc, srcData)) {
+ GrGLTexture::TexParams initialTexParams = set_initial_texture_params(this->glInterface(),
+ idDesc);
+
+ if (!this->uploadCompressedTexData(desc, GR_GL_TEXTURE_2D, texels)) {
GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
return return_null_texture();
}
@@ -1476,7 +1706,7 @@ bool GrGLGpu::flushGLState(const DrawArgs& args) {
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
this->flushStencil(pipeline.getStencil());
this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin());
- this->flushHWAAState(glRT, pipeline.isHWAntialiasState());
+ this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled());
// This must come after textures are flushed because a texture may need
// to be msaa-resolved (which will modify bound FBO state).
@@ -1899,6 +2129,22 @@ bool GrGLGpu::onReadPixels(GrSurface* surface,
return true;
}
+void GrGLGpu::setColocatedSampleLocations(GrRenderTarget* rt, bool useColocatedSampleLocations) {
+ GrGLRenderTarget* target = static_cast<GrGLRenderTarget*>(rt->asRenderTarget());
+ SkASSERT(0 != target->renderFBOID());
+
+ if (!rt->isStencilBufferMultisampled() ||
+ useColocatedSampleLocations == target->usesColocatedSampleLocations()) {
+ return;
+ }
+
+ GL_CALL(NamedFramebufferParameteri(target->renderFBOID(),
+ GR_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS,
+ useColocatedSampleLocations));
+
+ target->flagAsUsingColocatedSampleLocations(useColocatedSampleLocations);
+}
+
void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) {
SkASSERT(target);
@@ -2146,9 +2392,19 @@ void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) {
}
}
-void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA) {
+void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled) {
SkASSERT(!useHWAA || rt->isStencilBufferMultisampled());
+ if (rt->hasMixedSamples() && stencilEnabled &&
+ this->glCaps().glslCaps()->programmableSampleLocationsSupport()) {
+ if (useHWAA) {
+ this->setColocatedSampleLocations(rt, false);
+ } else {
+ this->setColocatedSampleLocations(rt, true);
+ }
+ useHWAA = true;
+ }
+
if (this->glCaps().multisampleDisableSupport()) {
if (useHWAA) {
if (kYes_TriState != fMSAAEnabled) {
@@ -2246,6 +2502,18 @@ static inline GrGLenum tile_to_gl_wrap(SkShader::TileMode tm) {
void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture) {
SkASSERT(texture);
+#ifdef SK_DEBUG
+ if (!this->caps()->npotTextureTileSupport()) {
+ const bool tileX = SkShader::kClamp_TileMode != params.getTileModeX();
+ const bool tileY = SkShader::kClamp_TileMode != params.getTileModeY();
+ if (tileX || tileY) {
+ const int w = texture->width();
+ const int h = texture->height();
+ SkASSERT(SkIsPow2(w) && SkIsPow2(h));
+ }
+ }
+#endif
+
// If we created a rt/tex and rendered to it without using a texture and now we're texturing
// from the rt it will still be the last bound texture, but it needs resolving. So keep this
// out of the "last != next" check.
@@ -2255,9 +2523,10 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
}
uint32_t textureID = texture->getUniqueID();
+ GrGLenum target = texture->target();
if (fHWBoundTextureUniqueIDs[unitIdx] != textureID) {
this->setTextureUnit(unitIdx);
- GL_CALL(BindTexture(GR_GL_TEXTURE_2D, texture->textureID()));
+ GL_CALL(BindTexture(target, texture->textureID()));
fHWBoundTextureUniqueIDs[unitIdx] = textureID;
}
@@ -2289,7 +2558,7 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
if (GrTextureParams::kMipMap_FilterMode == filterMode &&
texture->texturePriv().mipMapsAreDirty()) {
- GL_CALL(GenerateMipmap(GR_GL_TEXTURE_2D));
+ GL_CALL(GenerateMipmap(target));
texture->texturePriv().dirtyMipMaps(false);
}
@@ -2300,27 +2569,19 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
sizeof(newTexParams.fSwizzleRGBA));
if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) {
this->setTextureUnit(unitIdx);
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MAG_FILTER,
- newTexParams.fMagFilter));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMagFilter));
}
if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) {
this->setTextureUnit(unitIdx);
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_MIN_FILTER,
- newTexParams.fMinFilter));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMinFilter));
}
if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) {
this->setTextureUnit(unitIdx);
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_S,
- newTexParams.fWrapS));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS));
}
if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) {
this->setTextureUnit(unitIdx);
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
- GR_GL_TEXTURE_WRAP_T,
- newTexParams.fWrapT));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT));
}
if (this->glCaps().textureSwizzleSupport() &&
(setAll || memcmp(newTexParams.fSwizzleRGBA,
@@ -2330,14 +2591,14 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
if (this->glStandard() == kGLES_GrGLStandard) {
// ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
const GrGLenum* swizzle = newTexParams.fSwizzleRGBA;
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, swizzle[1]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, swizzle[2]));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, swizzle[3]));
} else {
GR_STATIC_ASSERT(sizeof(newTexParams.fSwizzleRGBA[0]) == sizeof(GrGLint));
const GrGLint* swizzle = reinterpret_cast<const GrGLint*>(newTexParams.fSwizzleRGBA);
- GL_CALL(TexParameteriv(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_SWIZZLE_RGBA, swizzle));
+ GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA, swizzle));
}
}
texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
@@ -2550,7 +2811,7 @@ bool GrGLGpu::configToGLFormats(GrPixelConfig config,
*externalType = GR_GL_HALF_FLOAT_OES;
}
break;
-
+
case kRGBA_half_GrPixelConfig:
*internalFormat = GR_GL_RGBA16F;
*externalFormat = GR_GL_RGBA;
@@ -2643,12 +2904,13 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
// If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is
// relative to is output.
-GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
- TempFBOTarget tempFBOTarget) {
+void GrGLGpu::bindSurfaceFBOForCopy(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
+ TempFBOTarget tempFBOTarget) {
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
if (nullptr == rt) {
SkASSERT(surface->asTexture());
GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID();
+ GrGLenum target = static_cast<GrGLTexture*>(surface->asTexture())->target();
GrGLuint* tempFBOID;
tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID;
@@ -2660,29 +2922,31 @@ GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLI
GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, *tempFBOID));
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
GR_GL_COLOR_ATTACHMENT0,
- GR_GL_TEXTURE_2D,
+ target,
texID,
0));
viewport->fLeft = 0;
viewport->fBottom = 0;
viewport->fWidth = surface->width();
viewport->fHeight = surface->height();
- return *tempFBOID;
} else {
- GrGLuint tempFBOID = 0;
fStats.incRenderTargetBinds();
GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID()));
*viewport = rt->getViewport();
- return tempFBOID;
}
}
-void GrGLGpu::unbindTextureFromFBO(GrGLenum fboTarget) {
- GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
- GR_GL_COLOR_ATTACHMENT0,
- GR_GL_TEXTURE_2D,
- 0,
- 0));
+void GrGLGpu::unbindTextureFBOForCopy(GrGLenum fboTarget, GrSurface* surface) {
+ // bindSurfaceFBOForCopy temporarily binds textures that are not render targets to
+ if (!surface->asRenderTarget()) {
+ SkASSERT(surface->asTexture());
+ GrGLenum textureTarget = static_cast<GrGLTexture*>(surface->asTexture())->target();
+ GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
+ GR_GL_COLOR_ATTACHMENT0,
+ textureTarget,
+ 0,
+ 0));
+ }
}
bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const {
@@ -2745,7 +3009,7 @@ bool GrGLGpu::onCopySurface(GrSurface* dst,
this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
return true;
}
-
+
if (can_copy_texsubimage(dst, src, this)) {
this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint);
return true;
@@ -2769,7 +3033,7 @@ void GrGLGpu::createCopyProgram() {
GrGLShaderVar uTexture("u_texture", kSampler2D_GrSLType, GrShaderVar::kUniform_TypeModifier);
GrGLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier);
GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
-
+
SkString vshaderTxt(version);
aVertex.appendDecl(this->ctxInfo(), &vshaderTxt);
vshaderTxt.append(";");
@@ -2779,7 +3043,7 @@ void GrGLGpu::createCopyProgram() {
vshaderTxt.append(";");
vTexCoord.appendDecl(this->ctxInfo(), &vshaderTxt);
vshaderTxt.append(";");
-
+
vshaderTxt.append(
"// Copy Program VS\n"
"void main() {"
@@ -2813,7 +3077,7 @@ void GrGLGpu::createCopyProgram() {
fsOutName,
GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration())
);
-
+
GL_CALL_RET(fCopyProgram.fProgram, CreateProgram());
const char* str;
GrGLint length;
@@ -2916,7 +3180,7 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
this->flushBlend(blendInfo);
this->flushColorWrite(true);
this->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace);
- this->flushHWAAState(dstRT, false);
+ this->flushHWAAState(dstRT, false, false);
this->disableScissor();
GrStencilSettings stencil;
stencil.setDisabled();
@@ -2930,9 +3194,8 @@ void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
SkASSERT(can_copy_texsubimage(dst, src, this));
- GrGLuint srcFBO;
GrGLIRect srcVP;
- srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
+ this->bindSurfaceFBOForCopy(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture());
SkASSERT(dstTex);
// We modified the bound FBO
@@ -2946,20 +3209,18 @@ void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst,
src->origin());
this->setScratchTextureUnit();
- GL_CALL(BindTexture(GR_GL_TEXTURE_2D, dstTex->textureID()));
+ GL_CALL(BindTexture(dstTex->target(), dstTex->textureID()));
GrGLint dstY;
if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
} else {
dstY = dstPoint.fY;
}
- GL_CALL(CopyTexSubImage2D(GR_GL_TEXTURE_2D, 0,
+ GL_CALL(CopyTexSubImage2D(dstTex->target(), 0,
dstPoint.fX, dstY,
srcGLRect.fLeft, srcGLRect.fBottom,
srcGLRect.fWidth, srcGLRect.fHeight));
- if (srcFBO) {
- this->unbindTextureFromFBO(GR_GL_FRAMEBUFFER);
- }
+ this->unbindTextureFBOForCopy(GR_GL_FRAMEBUFFER, src);
}
bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst,
@@ -2975,14 +3236,10 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst,
}
}
- GrGLuint dstFBO;
- GrGLuint srcFBO;
GrGLIRect dstVP;
GrGLIRect srcVP;
- dstFBO = this->bindSurfaceAsFBO(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP,
- kDst_TempFBOTarget);
- srcFBO = this->bindSurfaceAsFBO(src, GR_GL_READ_FRAMEBUFFER, &srcVP,
- kSrc_TempFBOTarget);
+ this->bindSurfaceFBOForCopy(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);
+ this->bindSurfaceFBOForCopy(src, GR_GL_READ_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
// We modified the bound FBO
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
GrGLIRect srcGLRect;
@@ -3022,12 +3279,8 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst,
dstGLRect.fLeft + dstGLRect.fWidth,
dstGLRect.fBottom + dstGLRect.fHeight,
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
- if (dstFBO) {
- this->unbindTextureFromFBO(GR_GL_DRAW_FRAMEBUFFER);
- }
- if (srcFBO) {
- this->unbindTextureFromFBO(GR_GL_READ_FRAMEBUFFER);
- }
+ this->unbindTextureFBOForCopy(GR_GL_DRAW_FRAMEBUFFER, dst);
+ this->unbindTextureFBOForCopy(GR_GL_READ_FRAMEBUFFER, src);
return true;
}
« include/gpu/GrContext.h ('K') | « src/gpu/gl/GrGLGpu.h ('k') | src/image/SkImage_Gpu.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698