blob: e30269404364f4df5e89ba79dc79a72255e356a2 [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
18const GrGLenum* GrGLTexture::WrapMode2GLWrap(GrGLBinding binding) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +000019 static const GrGLenum mirrorRepeatModes[] = {
20 GR_GL_CLAMP_TO_EDGE,
21 GR_GL_REPEAT,
22 GR_GL_MIRRORED_REPEAT
23 };
24
25 static const GrGLenum repeatModes[] = {
26 GR_GL_CLAMP_TO_EDGE,
27 GR_GL_REPEAT,
28 GR_GL_REPEAT
29 };
30
bsalomon@google.com0b77d682011-08-19 13:28:54 +000031 if (kES1_GrGLBinding == binding) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +000032 return repeatModes; // GL_MIRRORED_REPEAT not supported.
33 } else {
34 return mirrorRepeatModes;
35 }
reed@google.comac10a2d2010-12-22 21:39:39 +000036};
37
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000038void GrGLTexture::init(GrGpuGL* gpu,
39 const Desc& textureDesc,
40 const GrGLRenderTarget::Desc* rtDesc,
41 const TexParams& initialTexParams) {
42
43 GrAssert(0 != textureDesc.fTextureID);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000044
45 fTexParams = initialTexParams;
bsalomon@google.com0b77d682011-08-19 13:28:54 +000046 fTexIDObj = new GrGLTexID(GPUGL->glInterface(),
47 textureDesc.fTextureID,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +000048 textureDesc.fOwnsID);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000049 fUploadFormat = textureDesc.fUploadFormat;
50 fUploadByteCount = textureDesc.fUploadByteCount;
51 fUploadType = textureDesc.fUploadType;
52 fOrientation = textureDesc.fOrientation;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000053 fScaleX = GrIntToScalar(textureDesc.fContentWidth) /
54 textureDesc.fAllocWidth;
55 fScaleY = GrIntToScalar(textureDesc.fContentHeight) /
56 textureDesc.fAllocHeight;
reed@google.comac10a2d2010-12-22 21:39:39 +000057
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000058 if (NULL != rtDesc) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +000059 // we render to the top left
60 GrGLIRect vp;
reed@google.comac10a2d2010-12-22 21:39:39 +000061 vp.fLeft = 0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +000062 vp.fWidth = textureDesc.fContentWidth;
63 vp.fHeight = textureDesc.fContentHeight;
64 vp.fBottom = textureDesc.fAllocHeight - textureDesc.fContentHeight;
65
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000066 fRenderTarget = new GrGLRenderTarget(gpu, *rtDesc, vp, fTexIDObj, this);
reed@google.comac10a2d2010-12-22 21:39:39 +000067 }
reed@google.comac10a2d2010-12-22 21:39:39 +000068}
69
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000070GrGLTexture::GrGLTexture(GrGpuGL* gpu,
71 const Desc& textureDesc,
72 const TexParams& initialTexParams)
73 : INHERITED(gpu,
74 textureDesc.fContentWidth,
75 textureDesc.fContentHeight,
bsalomon@google.com0168afc2011-08-08 13:21:05 +000076 textureDesc.fAllocWidth,
77 textureDesc.fAllocHeight,
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000078 textureDesc.fFormat) {
79 this->init(gpu, textureDesc, NULL, initialTexParams);
80}
81
82GrGLTexture::GrGLTexture(GrGpuGL* gpu,
83 const Desc& textureDesc,
84 const GrGLRenderTarget::Desc& rtDesc,
85 const TexParams& initialTexParams)
86 : INHERITED(gpu,
87 textureDesc.fContentWidth,
88 textureDesc.fContentHeight,
bsalomon@google.com0168afc2011-08-08 13:21:05 +000089 textureDesc.fAllocWidth,
90 textureDesc.fAllocHeight,
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000091 textureDesc.fFormat) {
92 this->init(gpu, textureDesc, &rtDesc, initialTexParams);
93}
94
bsalomon@google.com8fe72472011-03-30 21:26:44 +000095void GrGLTexture::onRelease() {
bsalomon@google.com6dcf4992011-04-05 21:16:14 +000096 INHERITED::onRelease();
Scroggoc29d7cd2011-06-16 13:14:21 +000097 GPUGL->notifyTextureDelete(this);
bsalomon@google.com8fe72472011-03-30 21:26:44 +000098 if (NULL != fTexIDObj) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +000099 fTexIDObj->unref();
100 fTexIDObj = NULL;
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000101 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000102}
103
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000104void GrGLTexture::onAbandon() {
bsalomon@google.com6dcf4992011-04-05 21:16:14 +0000105 INHERITED::onAbandon();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000106 if (NULL != fTexIDObj) {
107 fTexIDObj->abandon();
108 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000109}
110
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000111void GrGLTexture::uploadTextureData(int x,
112 int y,
113 int width,
114 int height,
junov@google.com4ee7ae52011-06-30 17:30:49 +0000115 const void* srcData,
116 size_t rowBytes) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000117
118 GPUGL->setSpareTextureUnit();
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000119
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000120 // ES2 glCompressedTexSubImage2D doesn't support any formats
reed@google.comac10a2d2010-12-22 21:39:39 +0000121 // (at least without extensions)
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000122 GrAssert(fUploadFormat != GR_GL_PALETTE8_RGBA8);
reed@google.comac10a2d2010-12-22 21:39:39 +0000123
junov@google.com4ee7ae52011-06-30 17:30:49 +0000124 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000125 SkAutoSMalloc<128 * 128> tempStorage;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000126
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000127 if (!rowBytes) {
128 rowBytes = fUploadByteCount * width;
129 }
junov@google.com4ee7ae52011-06-30 17:30:49 +0000130 /*
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000131 * check whether to allocate a temporary buffer for flipping y or
132 * because our srcData has extra bytes past each row. If so, we need
133 * to trim those off here, since GL ES doesn't let us specify
134 * GL_UNPACK_ROW_LENGTH.
junov@google.com4ee7ae52011-06-30 17:30:49 +0000135 */
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000136 bool restoreGLRowLength = false;
137 bool flipY = kBottomUp_Orientation == fOrientation;
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000138 if (kDesktop_GrGLBinding == GPUGL->glBinding() && !flipY) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000139 // can't use this for flipping, only non-neg values allowed. :(
junov@google.com4ee7ae52011-06-30 17:30:49 +0000140 if (srcData && rowBytes) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000141 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
junov@google.com4ee7ae52011-06-30 17:30:49 +0000142 rowBytes / fUploadByteCount));
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000143 restoreGLRowLength = true;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000144 }
145 } else {
146 size_t trimRowBytes = width * fUploadByteCount;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000147 if (srcData && (trimRowBytes < rowBytes || flipY)) {
junov@google.com4ee7ae52011-06-30 17:30:49 +0000148 // copy the data into our new storage, skipping the trailing bytes
149 size_t trimSize = height * trimRowBytes;
150 const char* src = (const char*)srcData;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000151 if (flipY) {
152 src += (height - 1) * rowBytes;
153 }
bsalomon@google.com7d4679a2011-09-02 22:06:24 +0000154 char* dst = (char*)tempStorage.reset(trimSize);
junov@google.com4ee7ae52011-06-30 17:30:49 +0000155 for (int y = 0; y < height; y++) {
156 memcpy(dst, src, trimRowBytes);
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000157 if (flipY) {
158 src -= rowBytes;
159 } else {
160 src += rowBytes;
161 }
junov@google.com4ee7ae52011-06-30 17:30:49 +0000162 dst += trimRowBytes;
163 }
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000164 // now point srcData to our copied version
165 srcData = tempStorage.get();
junov@google.com4ee7ae52011-06-30 17:30:49 +0000166 }
167 }
168
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000169 if (flipY) {
170 y = this->height() - (y + height);
171 }
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000172 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, fTexIDObj->id()));
173 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, fUploadByteCount));
174 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, x, y, width, height,
175 fUploadFormat, fUploadType, srcData));
reed@google.comac10a2d2010-12-22 21:39:39 +0000176
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000177 if (kDesktop_GrGLBinding == GPUGL->glBinding()) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000178 if (restoreGLRowLength) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000179 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
junov@google.com4ee7ae52011-06-30 17:30:49 +0000180 }
181 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000182}
183
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000184intptr_t GrGLTexture::getTextureHandle() const {
bsalomon@google.com1da07462011-03-10 14:51:57 +0000185 return fTexIDObj->id();
reed@google.comac10a2d2010-12-22 21:39:39 +0000186}
187