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

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: Created 5 years, 5 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
« src/gpu/SkGr.cpp ('K') | « src/gpu/gl/GrGLGpu.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/gl/GrGLGpu.cpp
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 5c03ab57d28a1b52cf0bb7463d7c2498ba8de64c..bb4821db62ba7dae42962485c529cd272b01f8c2 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -473,7 +473,7 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
GrSurfaceDesc surfDesc;
idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
-
+
switch (ownership) {
case kAdopt_GrWrapOwnership:
idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
@@ -481,7 +481,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;
@@ -531,7 +531,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
case kBorrow_GrWrapOwnership:
idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
break;
- }
+ }
idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig;
GrSurfaceDesc desc;
@@ -631,36 +631,10 @@ 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 (!adjust_pixel_ops_params(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()) {
+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
@@ -668,114 +642,245 @@ 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;
+}
+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;
+}
+
+static void prepare_image_for_writing_to_texture(const GrSurfaceDesc& desc, const GrGLCaps& caps,
+ bool swFlipY, bool glFlipY, int width, int height,
+ int bpp, size_t rowBytes, const void*& data,
+ SkAutoSMalloc<128 * 128>& tempStorage,
+ const GrGLInterface* interface,
+ bool& restoreGLRowLength) {
+ if (NULL == interface) {
+ return;
}
+ size_t trimRowBytes = width * 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.
*/
- 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;
- }
+ restoreGLRowLength = false;
+
+ 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);
+ GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
+ restoreGLRowLength = true;
}
- if (this->glCaps().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;
+ } else {
+ 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;
+ if (swFlipY) {
+ src += (height - 1) * rowBytes;
}
- } else {
- 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;
+ char* dst = (char*)tempStorage.reset(trimSize);
+ for (int y = 0; y < height; y++) {
+ memcpy(dst, src, trimRowBytes);
if (swFlipY) {
- src += (height - 1) * rowBytes;
- }
- char* dst = (char*)tempStorage.reset(trimSize);
- for (int y = 0; y < height; y++) {
- memcpy(dst, src, trimRowBytes);
- if (swFlipY) {
- src -= rowBytes;
- } else {
- src += rowBytes;
- }
- dst += trimRowBytes;
+ src -= rowBytes;
+ } else {
+ src += rowBytes;
}
- // now point data to our copied version
- data = tempStorage.get();
+ dst += trimRowBytes;
}
+ // now point data to our copied version
+ data = tempStorage.get();
}
- if (glFlipY) {
- GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
- }
- GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT,
- static_cast<GrGLint>(GrUnpackAlignment(dataConfig))));
}
- 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));
- } else {
- GL_ALLOC_CALL(this->glInterface(),
+ if (glFlipY) {
+ GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
+ }
+ GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT,
+ static_cast<GrGLint>(GrUnpackAlignment(desc.fConfig))));
+}
+
+static void allocate_and_populate_uncompressed_texture(const GrGLInterface* interface,
+ bool useTexStorage,
+ GrGLenum internalFormat,
+ GrGLenum externalFormat,
+ GrGLenum externalType,
+ const GrSurfaceDesc& desc,
+ SkTArray<const void*>& data,
+ bool& succeeded) {
+ CLEAR_ERROR_BEFORE_ALLOC(interface);
+ if (useTexStorage) {
+ // We never resize or change formats of textures.
+ GL_ALLOC_CALL(interface,
+ TexStorage2D(GR_GL_TEXTURE_2D,
+ data.count(),
+ internalFormat,
+ desc.fWidth, desc.fHeight));
+ } else {
+ int width = desc.fWidth;
+ int height = desc.fHeight;
+ for (int currentMipLevel = 0; currentMipLevel < data.count(); currentMipLevel++) {
+ GL_ALLOC_CALL(interface,
TexImage2D(GR_GL_TEXTURE_2D,
- 0, // level
+ currentMipLevel,
internalFormat,
- desc.fWidth, desc.fHeight,
+ width, height,
0, // border
externalFormat, externalType,
- data));
+ data[currentMipLevel]));
+ width /= 2;
+ height /= 2;
}
- GrGLenum error = check_alloc_error(desc, this->glInterface());
- if (error != GR_GL_NO_ERROR) {
- succeeded = false;
+ }
+
+ GrGLenum error = check_alloc_error(desc, interface);
+ if (error != GR_GL_NO_ERROR) {
+ succeeded = false;
+ } else {
+ int width = desc.fWidth;
+ int height = desc.fHeight;
+ for (int currentMipLevel = data.count(); currentMipLevel != 0; currentMipLevel--) {
+ auto currentMipData = data[currentMipLevel];
+ GR_GL_CALL(interface,
+ TexSubImage2D(GR_GL_TEXTURE_2D,
+ currentMipLevel,
+ 0, // left
+ 0, // top
+ width, height,
+ externalFormat, externalType,
+ currentMipData));
+ width /= 2;
+ height /= 2;
+ }
+ }
+}
+
+static bool allocate_and_populate_compressed_texture(const GrGLInterface* interface,
+ bool useTexStorage, GrGLenum internalFormat,
+ const GrSurfaceDesc& desc,
+ SkTArray<const void*>& data,
+ size_t dataSize) {
+ CLEAR_ERROR_BEFORE_ALLOC(interface);
+ if (useTexStorage) {
+ // We never resize or change formats of textures.
+ GL_ALLOC_CALL(interface,
+ TexStorage2D(GR_GL_TEXTURE_2D,
+ data.count(),
+ internalFormat,
+ desc.fWidth, desc.fHeight));
+ } else {
+ int width = desc.fWidth;
+ int height = desc.fHeight;
+ for (int currentMipLevel = 0; currentMipLevel < data.count(); currentMipLevel++) {
+ GL_ALLOC_CALL(interface,
+ CompressedTexImage2D(GR_GL_TEXTURE_2D,
+ data.count(),
+ internalFormat,
+ width, height,
+ 0, // border
+ SkToInt(dataSize),
+ data[currentMipLevel]));
+ width /= 2;
+ height /= 2;
+ }
+ }
+
+ GrGLenum error = check_alloc_error(desc, interface);
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ }
+ return true;
+}
+
+static void restore_gl_state(bool restoreGLRowLength, const GrGLInterface* interface,
+ const GrGLCaps& caps, bool glFlipY) {
+ if (restoreGLRowLength) {
+ SkASSERT(caps.unpackRowLengthSupport());
+ GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
+ }
+ if (glFlipY) {
+ GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
+ }
+}
+
+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 (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top,
+ &width, &height, &data, &rowBytes)) {
+ return false;
+ }
+
+ bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(),
+ desc);
+ bool useSizedFormat = can_use_sized_format(useTexStorage, this->glCaps(), this->glStandard(),
+ this->glVersion(), 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 (glCaps().unpackFlipYSupport()) {
+ glFlipY = true;
} 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));
- }
+ swFlipY = true;
}
+ }
+
+ bool restoreGLRowLength = false;
+
+ // in case we need a temporary, trimmed copy of the src pixels
+ SkAutoSMalloc<128 * 128> tempStorage;
+ if (data) {
+ prepare_image_for_writing_to_texture(desc, this->glCaps(), swFlipY, glFlipY, width, height,
+ bpp, rowBytes, data, tempStorage, this->glInterface(),
+ restoreGLRowLength);
+ }
+ bool succeeded = true;
+ if (isNewTexture &&
+ 0 == left && 0 == top &&
+ desc.fWidth == width && desc.fHeight == height) {
+ const int mipLevelCount = 1;
+ SkTArray<const void*> mipLevels(mipLevelCount);
+ mipLevels[0] = data;
+ allocate_and_populate_uncompressed_texture(this->glInterface(), useTexStorage,
+ internalFormat, externalFormat, externalType,
+ desc, mipLevels, succeeded);
} else {
if (swFlipY || glFlipY) {
top = desc.fHeight - (top + height);
@@ -787,13 +892,8 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
externalFormat, externalType, data));
}
- if (restoreGLRowLength) {
- SkASSERT(this->glCaps().unpackRowLengthSupport());
- GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
- }
- if (glFlipY) {
- GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
- }
+ restore_gl_state(restoreGLRowLength, this->glInterface(), this->glCaps(), glFlipY);
+
return succeeded;
}
@@ -829,6 +929,9 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
}
#endif
+ bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(),
+ desc);
+
// 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);
@@ -840,19 +943,11 @@ 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;
- }
+ const int mipLevelCount = 1;
+ SkTArray<const void*> mipLevels(mipLevelCount);
+ mipLevels[0] = data;
+ return allocate_and_populate_compressed_texture(this->glInterface(), useTexStorage,
+ internalFormat, desc, mipLevels, dataSize);
} else {
// Paletted textures can't be updated.
if (GR_GL_PALETTE8_RGBA8 == internalFormat) {
@@ -870,6 +965,99 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
return true;
}
+bool GrGLGpu::uploadMipmappedTexData(const GrSurfaceDesc& desc,
+ const SkMipMap& data) {
+ // If we're uploading compressed data then we should be using uploadCompressedMipmappedTexData
+ SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
+
+ size_t bpp = GrBytesPerPixel(desc.fConfig);
+
+ bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(),
+ desc);
+ bool useSizedFormat = can_use_sized_format(useTexStorage, this->glCaps(), this->glStandard(),
+ this->glVersion(), desc.fConfig);
+
+ GrGLenum internalFormat = 0x0; // suppress warning
+ GrGLenum externalFormat = 0x0; // suppress warning
+ GrGLenum externalType = 0x0; // suppress warning
+
+ if (!this->configToGLFormats(desc.fConfig, useSizedFormat, &internalFormat,
+ &externalFormat, &externalType)) {
+ return false;
+ }
+
+ bool swFlipY = false;
+ bool glFlipY = false;
+
+ if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
+ if (glCaps().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;
+
+ bool succeeded = true;
+ auto mipLevelCount = data.getLevelsCount();
+ SkTArray<const void*> mipLevels(mipLevelCount);
+ for (int currentMipLevel = mipLevelCount; currentMipLevel != 0; currentMipLevel--) {
+ SkMipMap::Level currentMipData;
+ if (data.getLevel(currentMipLevel, &currentMipData)) {
+ mipLevels[currentMipLevel] = currentMipData.fPixels;
+
+ prepare_image_for_writing_to_texture(desc, this->glCaps(), swFlipY, glFlipY,
+ currentMipData.fWidth, currentMipData.fHeight,
+ bpp, currentMipData.fRowBytes,
+ mipLevels[currentMipLevel], tempStorage,
+ this->glInterface(), restoreGLRowLength);
+ }
+ }
+ allocate_and_populate_uncompressed_texture(this->glInterface(), useTexStorage, internalFormat,
+ externalFormat, externalType, desc, mipLevels,
+ succeeded);
+
+ restore_gl_state(restoreGLRowLength, this->glInterface(), this->glCaps(), glFlipY);
+
+ return succeeded;
+}
+
+bool GrGLGpu::uploadCompressedMipmappedTexData(const GrSurfaceDesc& desc,
+ const SkMipMap& data) {
+ // No support for software flip y, yet...
+ SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin);
+
+ // 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, desc.fWidth, desc.fHeight);
+
+ bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(),
+ desc);
+ bool useSizedFormat = can_use_sized_format(useTexStorage, this->glCaps(), this->glStandard(),
+ this->glVersion(), desc.fConfig);
+
+ // We only need the internal format for compressed 2D textures.
+ GrGLenum internalFormat = 0;
+ if (!this->configToGLFormats(desc.fConfig, false, &internalFormat, NULL, NULL)) {
+ return false;
+ }
+
+ auto mipLevelCount = data.getLevelsCount();
+ SkTArray<const void*> mipLevels(mipLevelCount);
+ for (int currentLevelIndex = mipLevelCount; currentLevelIndex != 0; currentLevelIndex--) {
+ SkMipMap::Level currentLevel;
+ if (data.getLevel(currentLevelIndex, &currentLevel)) {
+ mipLevels[currentLevelIndex] = currentLevel.fPixels;
+ }
+ }
+ return allocate_and_populate_compressed_texture(this->glInterface(), useTexStorage,
+ internalFormat, desc, mipLevels, dataSize);
+}
+
static bool renderbuffer_storage_msaa(const GrGLContext& ctx,
int sampleCount,
GrGLenum format,
@@ -1032,6 +1220,40 @@ 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;
+ return idDesc;
+}
+
+static GrGLTexture::TexParams set_initial_texture_params(const GrGLInterface* interface) {
+ // 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(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MAG_FILTER,
+ initialTexParams.fMagFilter));
+ GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MIN_FILTER,
+ initialTexParams.fMinFilter));
+ GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_S,
+ initialTexParams.fWrapS));
+ GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_T,
+ initialTexParams.fWrapT));
+ return initialTexParams;
+}
+
GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
GrGpuResource::LifeCycle lifeCycle,
const void* srcData, size_t rowBytes) {
@@ -1043,10 +1265,7 @@ 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;
-
+ auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle);
if (!idDesc.fTextureID) {
return return_null_texture();
}
@@ -1061,28 +1280,8 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
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));
+ auto initialTexParams = set_initial_texture_params(this->glInterface());
+
if (!this->uploadTexData(desc, true, 0, 0,
desc.fWidth, desc.fHeight,
desc.fConfig, srcData, rowBytes)) {
@@ -1120,10 +1319,7 @@ GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
return return_null_texture();
}
- GrGLTexture::IDDesc idDesc;
- GL_CALL(GenTextures(1, &idDesc.fTextureID));
- idDesc.fLifeCycle = lifeCycle;
-
+ auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle);
if (!idDesc.fTextureID) {
return return_null_texture();
}
@@ -1131,28 +1327,7 @@ GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
this->setScratchTextureUnit();
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 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));
+ auto initialTexParams = set_initial_texture_params(this->glInterface());
if (!this->uploadCompressedTexData(desc, srcData)) {
GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
@@ -1169,6 +1344,93 @@ GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
return tex;
}
+GrTexture* GrGLGpu::onCreateMipmappedTexture(const GrSurfaceDesc& desc,
+ GrGpuResource::LifeCycle lifeCycle,
+ const SkMipMap& srcData)
+{
+ // 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.");
+ return return_null_texture();
+ }
+
+ bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
+
+ auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle);
+ if (!idDesc.fTextureID) {
+ return return_null_texture();
+ }
+
+ if (renderTarget && this->glCaps().textureUsageSupport()) {
+ // provides a hint about how this texture will be used
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_USAGE,
+ GR_GL_FRAMEBUFFER_ATTACHMENT));
+ }
+
+ auto initialTexParams = set_initial_texture_params(this->glInterface());
+
+ if (!this->uploadMipmappedTexData(desc, srcData)) {
+ GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
+ return return_null_texture();
+ }
+
+ 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));
+ GrGLRenderTarget::IDDesc rtIDDesc;
+
+ if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fTextureID, &rtIDDesc)) {
+ GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
+ return return_null_texture();
+ }
+ tex = SkNEW_ARGS(GrGLTextureRenderTarget, (this, desc, idDesc, rtIDDesc));
+ } else {
+ tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc));
+ }
+ tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
+#ifdef TRACE_TEXTURE_CREATION
+ SkDebugf("--- new mipmapped texture [%d] size=(%d %d) config=%d\n",
+ glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig);
+#endif
+ return tex;
+}
+
+GrTexture* GrGLGpu::onCreateCompressedMipmappedTexture(const GrSurfaceDesc& desc,
+ GrGpuResource::LifeCycle lifeCycle,
+ const SkMipMap& srcData)
+{
+ // Make sure that we're not flipping Y.
+ if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
+ return return_null_texture();
+ }
+
+ auto 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));
+
+ auto initialTexParams = set_initial_texture_params(this->glInterface());
+
+ if (!this->uploadCompressedMipmappedTexData(desc, srcData)) {
+ GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
+ return return_null_texture();
+ }
+
+ GrGLTexture* tex;
+ tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc));
+ tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
+#ifdef TRACE_TEXTURE_CREATION
+ SkDebugf("--- new compressed mipmapped texture [%d] size=(%d %d) config=%d\n",
+ glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig);
+#endif
+ return tex;
+}
+
namespace {
const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount;
« src/gpu/SkGr.cpp ('K') | « src/gpu/gl/GrGLGpu.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698