blob: bbca5ed1759de810055f5a66d6e1779cd57980cd [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrGLTexture.h"
19#include "GrGpuGL.h"
20
bsalomon@google.com8fe72472011-03-30 21:26:44 +000021#define GPUGL static_cast<GrGpuGL*>(getGpu())
22
23GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu,
24 const GLRenderTargetIDs& ids,
bsalomon@google.com1da07462011-03-10 14:51:57 +000025 GrGLTexID* texID,
twiz@google.com0f31ca72011-03-18 17:38:11 +000026 GrGLuint stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +000027 bool isMultisampled,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +000028 const GrGLIRect& viewport,
bsalomon@google.com8fe72472011-03-30 21:26:44 +000029 GrGLTexture* texture)
bsalomon@google.comf954d8d2011-04-06 17:50:02 +000030 : INHERITED(gpu, texture, viewport.fWidth,
31 viewport.fHeight, stencilBits, isMultisampled) {
reed@google.comac10a2d2010-12-22 21:39:39 +000032 fRTFBOID = ids.fRTFBOID;
33 fTexFBOID = ids.fTexFBOID;
34 fStencilRenderbufferID = ids.fStencilRenderbufferID;
35 fMSColorRenderbufferID = ids.fMSColorRenderbufferID;
reed@google.comac10a2d2010-12-22 21:39:39 +000036 fViewport = viewport;
37 fOwnIDs = ids.fOwnIDs;
bsalomon@google.com1da07462011-03-10 14:51:57 +000038 fTexIDObj = texID;
39 GrSafeRef(fTexIDObj);
reed@google.comac10a2d2010-12-22 21:39:39 +000040}
41
bsalomon@google.com8fe72472011-03-30 21:26:44 +000042void GrGLRenderTarget::onRelease() {
Scroggoc29d7cd2011-06-16 13:14:21 +000043 GPUGL->notifyRenderTargetDelete(this);
reed@google.comac10a2d2010-12-22 21:39:39 +000044 if (fOwnIDs) {
45 if (fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +000046 GR_GL(DeleteFramebuffers(1, &fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +000047 }
48 if (fRTFBOID && fRTFBOID != fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +000049 GR_GL(DeleteFramebuffers(1, &fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +000050 }
51 if (fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +000052 GR_GL(DeleteRenderbuffers(1, &fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +000053 }
54 if (fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +000055 GR_GL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +000056 }
57 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +000058 fRTFBOID = 0;
59 fTexFBOID = 0;
60 fStencilRenderbufferID = 0;
61 fMSColorRenderbufferID = 0;
bsalomon@google.com1da07462011-03-10 14:51:57 +000062 GrSafeUnref(fTexIDObj);
bsalomon@google.com8fe72472011-03-30 21:26:44 +000063 fTexIDObj = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +000064}
65
bsalomon@google.com8fe72472011-03-30 21:26:44 +000066void GrGLRenderTarget::onAbandon() {
reed@google.comac10a2d2010-12-22 21:39:39 +000067 fRTFBOID = 0;
68 fTexFBOID = 0;
69 fStencilRenderbufferID = 0;
70 fMSColorRenderbufferID = 0;
bsalomon@google.com1da07462011-03-10 14:51:57 +000071 if (NULL != fTexIDObj) {
72 fTexIDObj->abandon();
bsalomon@google.com8fe72472011-03-30 21:26:44 +000073 fTexIDObj = NULL;
bsalomon@google.com1da07462011-03-10 14:51:57 +000074 }
reed@google.comac10a2d2010-12-22 21:39:39 +000075}
76
77
78////////////////////////////////////////////////////////////////////////////////
79
twiz@google.comb65e0cb2011-03-18 20:41:44 +000080const GrGLenum* GrGLTexture::WrapMode2GLWrap() {
81 static const GrGLenum mirrorRepeatModes[] = {
82 GR_GL_CLAMP_TO_EDGE,
83 GR_GL_REPEAT,
84 GR_GL_MIRRORED_REPEAT
85 };
86
87 static const GrGLenum repeatModes[] = {
88 GR_GL_CLAMP_TO_EDGE,
89 GR_GL_REPEAT,
90 GR_GL_REPEAT
91 };
92
93 if (GR_GL_SUPPORT_ES1 && !GR_GL_SUPPORT_ES2) {
94 return repeatModes; // GL_MIRRORED_REPEAT not supported.
95 } else {
96 return mirrorRepeatModes;
97 }
reed@google.comac10a2d2010-12-22 21:39:39 +000098};
99
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000100GrGLTexture::GrGLTexture(GrGpuGL* gpu,
101 const GLTextureDesc& textureDesc,
reed@google.comac10a2d2010-12-22 21:39:39 +0000102 const GLRenderTargetIDs& rtIDs,
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000103 const TexParams& initialTexParams)
104 : INHERITED(gpu,
105 textureDesc.fContentWidth,
106 textureDesc.fContentHeight,
107 textureDesc.fFormat) {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000108
109 fTexParams = initialTexParams;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000110 fTexIDObj = new GrGLTexID(textureDesc.fTextureID,
111 textureDesc.fOwnsID);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000112 fUploadFormat = textureDesc.fUploadFormat;
113 fUploadByteCount = textureDesc.fUploadByteCount;
114 fUploadType = textureDesc.fUploadType;
115 fOrientation = textureDesc.fOrientation;
116 fAllocWidth = textureDesc.fAllocWidth;
117 fAllocHeight = textureDesc.fAllocHeight;
118 fScaleX = GrIntToScalar(textureDesc.fContentWidth) /
119 textureDesc.fAllocWidth;
120 fScaleY = GrIntToScalar(textureDesc.fContentHeight) /
121 textureDesc.fAllocHeight;
reed@google.comac10a2d2010-12-22 21:39:39 +0000122
123 GrAssert(0 != textureDesc.fTextureID);
124
125 if (rtIDs.fTexFBOID) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000126 // we render to the top left
127 GrGLIRect vp;
reed@google.comac10a2d2010-12-22 21:39:39 +0000128 vp.fLeft = 0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000129 vp.fWidth = textureDesc.fContentWidth;
130 vp.fHeight = textureDesc.fContentHeight;
131 vp.fBottom = textureDesc.fAllocHeight - textureDesc.fContentHeight;
132
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000133 fRenderTarget = new GrGLRenderTarget(gpu, rtIDs, fTexIDObj,
bsalomon@google.com1da07462011-03-10 14:51:57 +0000134 textureDesc.fStencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000135 rtIDs.fRTFBOID != rtIDs.fTexFBOID,
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000136 vp, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000137 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000138}
139
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000140void GrGLTexture::onRelease() {
bsalomon@google.com6dcf4992011-04-05 21:16:14 +0000141 INHERITED::onRelease();
Scroggoc29d7cd2011-06-16 13:14:21 +0000142 GPUGL->notifyTextureDelete(this);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000143 if (NULL != fTexIDObj) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000144 fTexIDObj->unref();
145 fTexIDObj = NULL;
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000146 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000147}
148
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000149void GrGLTexture::onAbandon() {
bsalomon@google.com6dcf4992011-04-05 21:16:14 +0000150 INHERITED::onAbandon();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000151 if (NULL != fTexIDObj) {
152 fTexIDObj->abandon();
153 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000154}
155
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000156void GrGLTexture::uploadTextureData(int x,
157 int y,
158 int width,
159 int height,
junov@google.com4ee7ae52011-06-30 17:30:49 +0000160 const void* srcData,
161 size_t rowBytes) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000162
163 GPUGL->setSpareTextureUnit();
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000164
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000165 // ES2 glCompressedTexSubImage2D doesn't support any formats
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 // (at least without extensions)
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000167 GrAssert(fUploadFormat != GR_GL_PALETTE8_RGBA8);
reed@google.comac10a2d2010-12-22 21:39:39 +0000168
junov@google.com4ee7ae52011-06-30 17:30:49 +0000169 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000170 SkAutoSMalloc<128 * 128> tempStorage;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000171
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000172 if (!rowBytes) {
173 rowBytes = fUploadByteCount * width;
174 }
junov@google.com4ee7ae52011-06-30 17:30:49 +0000175 /*
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000176 * check whether to allocate a temporary buffer for flipping y or
177 * because our srcData has extra bytes past each row. If so, we need
178 * to trim those off here, since GL ES doesn't let us specify
179 * GL_UNPACK_ROW_LENGTH.
junov@google.com4ee7ae52011-06-30 17:30:49 +0000180 */
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000181 bool restoreGLRowLength = false;
182 bool flipY = kBottomUp_Orientation == fOrientation;
183 if (GR_GL_SUPPORT_DESKTOP && !flipY) {
184 // can't use this for flipping, only non-neg values allowed. :(
junov@google.com4ee7ae52011-06-30 17:30:49 +0000185 if (srcData && rowBytes) {
186 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
187 rowBytes / fUploadByteCount));
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000188 restoreGLRowLength = true;
junov@google.com4ee7ae52011-06-30 17:30:49 +0000189 }
190 } else {
191 size_t trimRowBytes = width * fUploadByteCount;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000192 if (srcData && (trimRowBytes < rowBytes || flipY)) {
junov@google.com4ee7ae52011-06-30 17:30:49 +0000193 // copy the data into our new storage, skipping the trailing bytes
194 size_t trimSize = height * trimRowBytes;
195 const char* src = (const char*)srcData;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000196 if (flipY) {
197 src += (height - 1) * rowBytes;
198 }
199 char* dst = (char*)tempStorage.realloc(trimSize);
junov@google.com4ee7ae52011-06-30 17:30:49 +0000200 for (int y = 0; y < height; y++) {
201 memcpy(dst, src, trimRowBytes);
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000202 if (flipY) {
203 src -= rowBytes;
204 } else {
205 src += rowBytes;
206 }
junov@google.com4ee7ae52011-06-30 17:30:49 +0000207 dst += trimRowBytes;
208 }
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000209 // now point srcData to our copied version
210 srcData = tempStorage.get();
junov@google.com4ee7ae52011-06-30 17:30:49 +0000211 }
212 }
213
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000214 if (flipY) {
215 y = this->height() - (y + height);
216 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000217 GR_GL(BindTexture(GR_GL_TEXTURE_2D, fTexIDObj->id()));
218 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, fUploadByteCount));
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000219 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, x, y, width, height,
reed@google.comac10a2d2010-12-22 21:39:39 +0000220 fUploadFormat, fUploadType, srcData));
221
junov@google.com4ee7ae52011-06-30 17:30:49 +0000222 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000223 if (restoreGLRowLength) {
junov@google.com4ee7ae52011-06-30 17:30:49 +0000224 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
225 }
226 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000227}
228
229intptr_t GrGLTexture::getTextureHandle() {
bsalomon@google.com1da07462011-03-10 14:51:57 +0000230 return fTexIDObj->id();
reed@google.comac10a2d2010-12-22 21:39:39 +0000231}
232