blob: 8bfc1857d4bf2ac5010bb9d8d4cd06924ab94210 [file] [log] [blame]
Jason Sams7e8aae72011-05-26 16:33:01 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
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 "rsdCore.h"
19#include "rsdBcc.h"
20#include "rsdRuntime.h"
21#include "rsdAllocation.h"
22
23#include "rsAllocation.h"
24
25#include <GLES/gl.h>
26#include <GLES2/gl2.h>
27#include <GLES/glext.h>
28
29using namespace android;
30using namespace android::renderscript;
31
32
33
34const static GLenum gFaceOrder[] = {
35 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
36 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
37 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
38 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
39 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
40 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
41};
42
43
Jason Sams66db3ab2011-05-26 17:05:51 -070044GLenum rsdTypeToGLType(RsDataType t) {
45 switch (t) {
46 case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5;
47 case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1;
48 case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4;
49
50 //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT;
51 case RS_TYPE_FLOAT_32: return GL_FLOAT;
52 case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE;
53 case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT;
54 case RS_TYPE_SIGNED_8: return GL_BYTE;
55 case RS_TYPE_SIGNED_16: return GL_SHORT;
56 default: break;
57 }
58 return 0;
59}
60
61GLenum rsdKindToGLFormat(RsDataKind k) {
62 switch (k) {
63 case RS_KIND_PIXEL_L: return GL_LUMINANCE;
64 case RS_KIND_PIXEL_A: return GL_ALPHA;
65 case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
66 case RS_KIND_PIXEL_RGB: return GL_RGB;
67 case RS_KIND_PIXEL_RGBA: return GL_RGBA;
68 case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
69 default: break;
70 }
71 return 0;
72}
73
74
Jason Sams7e8aae72011-05-26 16:33:01 -070075static void Update2DTexture(const Allocation *alloc, const void *ptr, uint32_t xoff, uint32_t yoff,
76 uint32_t lod, RsAllocationCubemapFace face,
77 uint32_t w, uint32_t h) {
78 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
79
Jason Sams7e8aae72011-05-26 16:33:01 -070080 rsAssert(drv->textureID);
81 glBindTexture(drv->glTarget, drv->textureID);
82 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
83 GLenum t = GL_TEXTURE_2D;
84 if (alloc->mHal.state.hasFaces) {
85 t = gFaceOrder[face];
86 }
Jason Sams66db3ab2011-05-26 17:05:51 -070087 glTexSubImage2D(t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
Jason Sams7e8aae72011-05-26 16:33:01 -070088}
89
90
91static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
92 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
93
Jason Sams7e8aae72011-05-26 16:33:01 -070094 glBindTexture(drv->glTarget, drv->textureID);
95 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
96
97 uint32_t faceCount = 1;
98 if (alloc->mHal.state.hasFaces) {
99 faceCount = 6;
100 }
101
102 rsdGLCheckError(rsc, "Upload2DTexture 1 ");
103 for (uint32_t face = 0; face < faceCount; face ++) {
104 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
105 const uint8_t *p = (const uint8_t *)drv->mallocPtr;
106 p += alloc->mHal.state.type->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
107
108 GLenum t = GL_TEXTURE_2D;
109 if (alloc->mHal.state.hasFaces) {
110 t = gFaceOrder[face];
111 }
112
113 if (isFirstUpload) {
Jason Sams66db3ab2011-05-26 17:05:51 -0700114 glTexImage2D(t, lod, drv->glFormat,
Jason Sams7e8aae72011-05-26 16:33:01 -0700115 alloc->mHal.state.type->getLODDimX(lod),
116 alloc->mHal.state.type->getLODDimY(lod),
Jason Sams66db3ab2011-05-26 17:05:51 -0700117 0, drv->glFormat, drv->glType, p);
Jason Sams7e8aae72011-05-26 16:33:01 -0700118 } else {
119 glTexSubImage2D(t, lod, 0, 0,
120 alloc->mHal.state.type->getLODDimX(lod),
121 alloc->mHal.state.type->getLODDimY(lod),
Jason Sams66db3ab2011-05-26 17:05:51 -0700122 drv->glFormat, drv->glType, p);
Jason Sams7e8aae72011-05-26 16:33:01 -0700123 }
124 }
125 }
126
127 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
128 glGenerateMipmap(drv->glTarget);
129 }
130 rsdGLCheckError(rsc, "Upload2DTexture");
131}
132
133static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
134 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
135
Jason Sams66db3ab2011-05-26 17:05:51 -0700136 if (!drv->glType || !drv->glFormat) {
Jason Sams7e8aae72011-05-26 16:33:01 -0700137 return;
138 }
139
140 if (!alloc->getPtr()) {
141 return;
142 }
143
144 bool isFirstUpload = false;
145
146 if (!drv->textureID) {
147 glGenTextures(1, &drv->textureID);
148 isFirstUpload = true;
149 }
150
151 Upload2DTexture(rsc, alloc, isFirstUpload);
152
153 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
154 if (drv->mallocPtr) {
155 free(drv->mallocPtr);
156 drv->mallocPtr = NULL;
157 }
158 }
159 rsdGLCheckError(rsc, "UploadToTexture");
160}
161
162static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
163 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
164
Jason Sams66db3ab2011-05-26 17:05:51 -0700165 if (!drv->glFormat) {
Jason Sams7e8aae72011-05-26 16:33:01 -0700166 return;
167 }
168
169 if (!drv->renderTargetID) {
170 glGenRenderbuffers(1, &drv->renderTargetID);
171
172 if (!drv->renderTargetID) {
173 // This should generally not happen
174 LOGE("allocateRenderTarget failed to gen mRenderTargetID");
175 rsc->dumpDebug();
176 return;
177 }
178 glBindRenderbuffer(GL_RENDERBUFFER, drv->renderTargetID);
Jason Sams66db3ab2011-05-26 17:05:51 -0700179 glRenderbufferStorage(GL_RENDERBUFFER, drv->glFormat,
Jason Sams7e8aae72011-05-26 16:33:01 -0700180 alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY);
181 }
182 rsdGLCheckError(rsc, "AllocateRenderTarget");
183}
184
185static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
186 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
187
188 rsAssert(!alloc->mHal.state.type->getDimY());
189 rsAssert(!alloc->mHal.state.type->getDimZ());
190
191 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
192
193 if (!drv->bufferID) {
194 glGenBuffers(1, &drv->bufferID);
195 }
196 if (!drv->bufferID) {
197 LOGE("Upload to buffer object failed");
198 drv->uploadDeferred = true;
199 return;
200 }
201 glBindBuffer(drv->glTarget, drv->bufferID);
202 glBufferData(drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
203 drv->mallocPtr, GL_DYNAMIC_DRAW);
204 glBindBuffer(drv->glTarget, 0);
205 rsdGLCheckError(rsc, "UploadToBufferObject");
206}
207
208bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
209 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
210 if (!drv) {
211 return false;
212 }
213
214 void * ptr = malloc(alloc->mHal.state.type->getSizeBytes());
215 if (!ptr) {
216 free(drv);
217 return false;
218 }
219
220 drv->glTarget = GL_NONE;
221 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
222 if (alloc->mHal.state.hasFaces) {
223 drv->glTarget = GL_TEXTURE_CUBE_MAP;
224 } else {
225 drv->glTarget = GL_TEXTURE_2D;
226 }
227 } else {
228 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
229 drv->glTarget = GL_ARRAY_BUFFER;
230 }
231 }
232
Jason Sams66db3ab2011-05-26 17:05:51 -0700233 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
234 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
235
236
Jason Sams7e8aae72011-05-26 16:33:01 -0700237 alloc->mHal.drvState.mallocPtr = ptr;
238 drv->mallocPtr = (uint8_t *)ptr;
239 alloc->mHal.drv = drv;
240 if (forceZero) {
241 memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
242 }
243
244 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
245 drv->uploadDeferred = true;
246 }
247 return true;
248}
249
250void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
251 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
252
253 if (drv->bufferID) {
254 // Causes a SW crash....
255 //LOGV(" mBufferID %i", mBufferID);
256 //glDeleteBuffers(1, &mBufferID);
257 //mBufferID = 0;
258 }
259 if (drv->textureID) {
260 glDeleteTextures(1, &drv->textureID);
261 drv->textureID = 0;
262 }
263 if (drv->renderTargetID) {
264 glDeleteRenderbuffers(1, &drv->renderTargetID);
265 drv->renderTargetID = 0;
266 }
267
268 if (drv->mallocPtr) {
269 free(drv->mallocPtr);
270 drv->mallocPtr = NULL;
271 }
272 free(drv);
273 alloc->mHal.drv = NULL;
274}
275
276void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
277 const Type *newType, bool zeroNew) {
278 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
279
280 drv->mallocPtr = (uint8_t *)realloc(drv->mallocPtr, newType->getSizeBytes());
281
282 // fixme
283 ((Allocation *)alloc)->mHal.drvState.mallocPtr = drv->mallocPtr;
284
285 const uint32_t oldDimX = alloc->mHal.state.dimensionX;
286 const uint32_t dimX = newType->getDimX();
287
288 if (dimX > oldDimX) {
289 const Element *e = alloc->mHal.state.type->getElement();
290 uint32_t stride = e->getSizeBytes();
291 memset(((uint8_t *)drv->mallocPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
292 }
293}
294
295
296
297void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
298 RsAllocationUsageType src) {
299 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
300
301 if (!drv->uploadDeferred) {
302 return;
303 }
304
305 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
306
307 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
308 UploadToTexture(rsc, alloc);
309 } else {
310 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
311 AllocateRenderTarget(rsc, alloc);
312 }
313 }
314 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
315 UploadToBufferObject(rsc, alloc);
316 }
317
318 drv->uploadDeferred = false;
319}
320
321void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
322 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
323 drv->uploadDeferred = true;
324}
325
326void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
327 uint32_t xoff, uint32_t lod, uint32_t count,
328 const void *data, uint32_t sizeBytes) {
329 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
330
331 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
332 uint8_t * ptr = drv->mallocPtr;
333 ptr += eSize * xoff;
334 uint32_t size = count * eSize;
335
336 if (alloc->mHal.state.hasReferences) {
337 alloc->incRefs(data, count);
338 alloc->decRefs(ptr, count);
339 }
340
341 memcpy(ptr, data, size);
342 drv->uploadDeferred = true;
343}
344
345void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
346 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
347 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
348 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
349
350 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
351 uint32_t lineSize = eSize * w;
352 uint32_t destW = alloc->mHal.state.dimensionX;
353
354 if (drv->mallocPtr) {
355 const uint8_t *src = static_cast<const uint8_t *>(data);
356 uint8_t *dst = drv->mallocPtr;
357 dst += alloc->mHal.state.type->getLODFaceOffset(lod, face, xoff, yoff);
358
359 for (uint32_t line=yoff; line < (yoff+h); line++) {
360 if (alloc->mHal.state.hasReferences) {
361 alloc->incRefs(src, w);
362 alloc->decRefs(dst, w);
363 }
364 memcpy(dst, src, lineSize);
365 src += lineSize;
366 dst += destW * eSize;
367 }
368 drv->uploadDeferred = true;
369 } else {
370 Update2DTexture(alloc, data, xoff, yoff, lod, face, w, h);
371 }
372}
373
374void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
375 uint32_t xoff, uint32_t yoff, uint32_t zoff,
376 uint32_t lod, RsAllocationCubemapFace face,
377 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
378
379}
380
Alex Sakhartchouk304b1f52011-06-14 11:13:19 -0700381void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
382 const android::renderscript::Allocation *dstAlloc,
383 uint32_t dstXoff, uint32_t dstLod, uint32_t count,
384 const android::renderscript::Allocation *srcAlloc,
385 uint32_t srcXoff, uint32_t srcLod){
386}
387
388void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
389 const android::renderscript::Allocation *dstAlloc,
390 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
391 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
392 const android::renderscript::Allocation *srcAlloc,
393 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
394 RsAllocationCubemapFace srcFace) {
395}
396
397void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
398 const android::renderscript::Allocation *dstAlloc,
399 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
400 uint32_t dstLod, RsAllocationCubemapFace dstFace,
401 uint32_t w, uint32_t h, uint32_t d,
402 const android::renderscript::Allocation *srcAlloc,
403 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
404 uint32_t srcLod, RsAllocationCubemapFace srcFace) {
405}
406
Jason Sams7e8aae72011-05-26 16:33:01 -0700407void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc,
408 uint32_t x,
409 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
410 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
411
412 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
413 uint8_t * ptr = drv->mallocPtr;
414 ptr += eSize * x;
415
416 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
417 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
418
419 if (alloc->mHal.state.hasReferences) {
420 e->incRefs(data);
421 e->decRefs(ptr);
422 }
423
424 memcpy(ptr, data, sizeBytes);
425 drv->uploadDeferred = true;
426}
427
428void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc,
429 uint32_t x, uint32_t y,
430 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
431 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
432
433 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
434 uint8_t * ptr = drv->mallocPtr;
435 ptr += eSize * (x + y * alloc->mHal.state.dimensionX);
436
437 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
438 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
439
440 if (alloc->mHal.state.hasReferences) {
441 e->incRefs(data);
442 e->decRefs(ptr);
443 }
444
445 memcpy(ptr, data, sizeBytes);
446 drv->uploadDeferred = true;
447}
448
449