blob: 06efb8a36b26626cf2d9ae9312e78875eeaeda7e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
10#include "GrGLTexture.h"
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000011
reed@google.comac10a2d2010-12-22 21:39:39 +000012#include "GrGpuGL.h"
13
bsalomon@google.com8fe72472011-03-30 21:26:44 +000014#define GPUGL static_cast<GrGpuGL*>(getGpu())
15
bsalomon@google.com0b77d682011-08-19 13:28:54 +000016#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
17
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000018const GrGLenum* GrGLTexture::WrapMode2GLWrap() {
19 static const GrGLenum repeatModes[] = {
twiz@google.comb65e0cb2011-03-18 20:41:44 +000020 GR_GL_CLAMP_TO_EDGE,
21 GR_GL_REPEAT,
22 GR_GL_MIRRORED_REPEAT
23 };
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000024 return repeatModes;
reed@google.comac10a2d2010-12-22 21:39:39 +000025};
26
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000027void GrGLTexture::init(GrGpuGL* gpu,
28 const Desc& textureDesc,
bsalomon@google.com80d09b92011-11-05 21:21:13 +000029 const GrGLRenderTarget::Desc* rtDesc) {
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000030
31 GrAssert(0 != textureDesc.fTextureID);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000032
bsalomon@google.com80d09b92011-11-05 21:21:13 +000033 fTexParams.invalidate();
34 fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
bsalomon@google.com0b77d682011-08-19 13:28:54 +000035 fTexIDObj = new GrGLTexID(GPUGL->glInterface(),
36 textureDesc.fTextureID,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +000037 textureDesc.fOwnsID);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000038 fUploadFormat = textureDesc.fUploadFormat;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000039 fUploadType = textureDesc.fUploadType;
40 fOrientation = textureDesc.fOrientation;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000041 fScaleX = GrIntToScalar(textureDesc.fContentWidth) /
42 textureDesc.fAllocWidth;
43 fScaleY = GrIntToScalar(textureDesc.fContentHeight) /
44 textureDesc.fAllocHeight;
reed@google.comac10a2d2010-12-22 21:39:39 +000045
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000046 if (NULL != rtDesc) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +000047 // we render to the top left
48 GrGLIRect vp;
reed@google.comac10a2d2010-12-22 21:39:39 +000049 vp.fLeft = 0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +000050 vp.fWidth = textureDesc.fContentWidth;
51 vp.fHeight = textureDesc.fContentHeight;
52 vp.fBottom = textureDesc.fAllocHeight - textureDesc.fContentHeight;
53
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000054 fRenderTarget = new GrGLRenderTarget(gpu, *rtDesc, vp, fTexIDObj, this);
reed@google.comac10a2d2010-12-22 21:39:39 +000055 }
reed@google.comac10a2d2010-12-22 21:39:39 +000056}
57
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000058GrGLTexture::GrGLTexture(GrGpuGL* gpu,
bsalomon@google.com80d09b92011-11-05 21:21:13 +000059 const Desc& textureDesc)
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000060 : INHERITED(gpu,
61 textureDesc.fContentWidth,
62 textureDesc.fContentHeight,
bsalomon@google.com0168afc2011-08-08 13:21:05 +000063 textureDesc.fAllocWidth,
64 textureDesc.fAllocHeight,
bsalomon@google.com64c4fe42011-11-05 14:51:01 +000065 textureDesc.fConfig) {
bsalomon@google.com80d09b92011-11-05 21:21:13 +000066 this->init(gpu, textureDesc, NULL);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000067}
68
69GrGLTexture::GrGLTexture(GrGpuGL* gpu,
70 const Desc& textureDesc,
bsalomon@google.com80d09b92011-11-05 21:21:13 +000071 const GrGLRenderTarget::Desc& rtDesc)
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000072 : INHERITED(gpu,
73 textureDesc.fContentWidth,
74 textureDesc.fContentHeight,
bsalomon@google.com0168afc2011-08-08 13:21:05 +000075 textureDesc.fAllocWidth,
76 textureDesc.fAllocHeight,
bsalomon@google.com64c4fe42011-11-05 14:51:01 +000077 textureDesc.fConfig) {
bsalomon@google.com80d09b92011-11-05 21:21:13 +000078 this->init(gpu, textureDesc, &rtDesc);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000079}
80
bsalomon@google.com8fe72472011-03-30 21:26:44 +000081void GrGLTexture::onRelease() {
bsalomon@google.com6dcf4992011-04-05 21:16:14 +000082 INHERITED::onRelease();
Scroggoc29d7cd2011-06-16 13:14:21 +000083 GPUGL->notifyTextureDelete(this);
bsalomon@google.com8fe72472011-03-30 21:26:44 +000084 if (NULL != fTexIDObj) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +000085 fTexIDObj->unref();
86 fTexIDObj = NULL;
bsalomon@google.com8fe72472011-03-30 21:26:44 +000087 }
reed@google.comac10a2d2010-12-22 21:39:39 +000088}
89
bsalomon@google.com8fe72472011-03-30 21:26:44 +000090void GrGLTexture::onAbandon() {
bsalomon@google.com6dcf4992011-04-05 21:16:14 +000091 INHERITED::onAbandon();
bsalomon@google.com8fe72472011-03-30 21:26:44 +000092 if (NULL != fTexIDObj) {
93 fTexIDObj->abandon();
94 }
reed@google.comac10a2d2010-12-22 21:39:39 +000095}
96
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +000097void GrGLTexture::uploadTextureData(int x,
98 int y,
99 int width,
100 int height,
junov@google.com4ee7ae52011-06-30 17:30:49 +0000101 const void* srcData,
102 size_t rowBytes) {
bsalomon@google.com9d6cfd82011-11-05 13:25:21 +0000103 GrIRect bounds = GrIRect::MakeWH(this->width(), this->height());
104 GrIRect subrect = GrIRect::MakeXYWH(x,y,width, height);
105 if (!bounds.contains(subrect)) {
106 return;
107 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000108 GPUGL->setSpareTextureUnit();
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000109
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000110 // ES2 glCompressedTexSubImage2D doesn't support any formats
reed@google.comac10a2d2010-12-22 21:39:39 +0000111 // (at least without extensions)
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000112 GrAssert(fUploadFormat != GR_GL_PALETTE8_RGBA8);
reed@google.comac10a2d2010-12-22 21:39:39 +0000113
junov@google.com4ee7ae52011-06-30 17:30:49 +0000114 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000115 SkAutoSMalloc<128 * 128> tempStorage;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000116
bsalomon@google.com9d6cfd82011-11-05 13:25:21 +0000117 size_t bpp = GrBytesPerPixel(this->config());
118 size_t trimRowBytes = width * bpp;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000119 if (!rowBytes) {
bsalomon@google.com9d6cfd82011-11-05 13:25:21 +0000120 rowBytes = trimRowBytes;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000121 }
junov@google.com4ee7ae52011-06-30 17:30:49 +0000122 /*
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000123 * check whether to allocate a temporary buffer for flipping y or
124 * because our srcData has extra bytes past each row. If so, we need
bsalomon@google.com7107fa72011-11-10 14:54:14 +0000125 * to trim those off here, since GL ES may not let us specify
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000126 * GL_UNPACK_ROW_LENGTH.
junov@google.com4ee7ae52011-06-30 17:30:49 +0000127 */
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000128 bool restoreGLRowLength = false;
129 bool flipY = kBottomUp_Orientation == fOrientation;
bsalomon@google.com7107fa72011-11-10 14:54:14 +0000130 if (GPUGL->glCaps().fUnpackRowLengthSupport && !flipY) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000131 // can't use this for flipping, only non-neg values allowed. :(
bsalomon@google.com9d6cfd82011-11-05 13:25:21 +0000132 if (srcData && rowBytes != trimRowBytes) {
133 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
134 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000135 restoreGLRowLength = true;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000136 }
137 } else {
bsalomon@google.com9d6cfd82011-11-05 13:25:21 +0000138 if (srcData && (trimRowBytes != rowBytes || flipY)) {
junov@google.com4ee7ae52011-06-30 17:30:49 +0000139 // copy the data into our new storage, skipping the trailing bytes
140 size_t trimSize = height * trimRowBytes;
141 const char* src = (const char*)srcData;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000142 if (flipY) {
143 src += (height - 1) * rowBytes;
144 }
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000145 char* dst = (char*)tempStorage.reset(trimSize);
junov@google.com4ee7ae52011-06-30 17:30:49 +0000146 for (int y = 0; y < height; y++) {
147 memcpy(dst, src, trimRowBytes);
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000148 if (flipY) {
149 src -= rowBytes;
150 } else {
151 src += rowBytes;
152 }
junov@google.com4ee7ae52011-06-30 17:30:49 +0000153 dst += trimRowBytes;
154 }
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000155 // now point srcData to our copied version
156 srcData = tempStorage.get();
junov@google.com4ee7ae52011-06-30 17:30:49 +0000157 }
158 }
159
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000160 if (flipY) {
161 y = this->height() - (y + height);
162 }
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000163 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, fTexIDObj->id()));
bsalomon@google.com9d6cfd82011-11-05 13:25:21 +0000164 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000165 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, x, y, width, height,
166 fUploadFormat, fUploadType, srcData));
reed@google.comac10a2d2010-12-22 21:39:39 +0000167
bsalomon@google.com7107fa72011-11-10 14:54:14 +0000168 if (restoreGLRowLength) {
169 GrAssert(GPUGL->glCaps().fUnpackRowLengthSupport);
170 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
junov@google.com4ee7ae52011-06-30 17:30:49 +0000171 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000172}
173
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000174intptr_t GrGLTexture::getTextureHandle() const {
bsalomon@google.com1da07462011-03-10 14:51:57 +0000175 return fTexIDObj->id();
reed@google.comac10a2d2010-12-22 21:39:39 +0000176}
177