blob: f58fe1a26b719de206d8220e8fa2dcfdd00e6562 [file] [log] [blame]
Jason Samseb4fe182011-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
44static void Update2DTexture(const Allocation *alloc, const void *ptr, uint32_t xoff, uint32_t yoff,
45 uint32_t lod, RsAllocationCubemapFace face,
46 uint32_t w, uint32_t h) {
47 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
48
49 const GLenum type = alloc->mHal.state.type->getElement()->getComponent().getGLType();
50 const GLenum format = alloc->mHal.state.type->getElement()->getComponent().getGLFormat();
51 rsAssert(drv->textureID);
52 glBindTexture(drv->glTarget, drv->textureID);
53 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
54 GLenum t = GL_TEXTURE_2D;
55 if (alloc->mHal.state.hasFaces) {
56 t = gFaceOrder[face];
57 }
58 glTexSubImage2D(t, lod, xoff, yoff, w, h, format, type, ptr);
59}
60
61
62static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
63 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
64
65 GLenum type = alloc->mHal.state.type->getElement()->getComponent().getGLType();
66 GLenum format = alloc->mHal.state.type->getElement()->getComponent().getGLFormat();
67
68 glBindTexture(drv->glTarget, drv->textureID);
69 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
70
71 uint32_t faceCount = 1;
72 if (alloc->mHal.state.hasFaces) {
73 faceCount = 6;
74 }
75
76 rsdGLCheckError(rsc, "Upload2DTexture 1 ");
77 for (uint32_t face = 0; face < faceCount; face ++) {
78 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
79 const uint8_t *p = (const uint8_t *)drv->mallocPtr;
80 p += alloc->mHal.state.type->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
81
82 GLenum t = GL_TEXTURE_2D;
83 if (alloc->mHal.state.hasFaces) {
84 t = gFaceOrder[face];
85 }
86
87 if (isFirstUpload) {
88 glTexImage2D(t, lod, format,
89 alloc->mHal.state.type->getLODDimX(lod),
90 alloc->mHal.state.type->getLODDimY(lod),
91 0, format, type, p);
92 } else {
93 glTexSubImage2D(t, lod, 0, 0,
94 alloc->mHal.state.type->getLODDimX(lod),
95 alloc->mHal.state.type->getLODDimY(lod),
96 format, type, p);
97 }
98 }
99 }
100
101 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
102 glGenerateMipmap(drv->glTarget);
103 }
104 rsdGLCheckError(rsc, "Upload2DTexture");
105}
106
107static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
108 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
109
110 GLenum type = alloc->mHal.state.type->getElement()->getComponent().getGLType();
111 GLenum format = alloc->mHal.state.type->getElement()->getComponent().getGLFormat();
112
113 if (!type || !format) {
114 return;
115 }
116
117 if (!alloc->getPtr()) {
118 return;
119 }
120
121 bool isFirstUpload = false;
122
123 if (!drv->textureID) {
124 glGenTextures(1, &drv->textureID);
125 isFirstUpload = true;
126 }
127
128 Upload2DTexture(rsc, alloc, isFirstUpload);
129
130 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
131 if (drv->mallocPtr) {
132 free(drv->mallocPtr);
133 drv->mallocPtr = NULL;
134 }
135 }
136 rsdGLCheckError(rsc, "UploadToTexture");
137}
138
139static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
140 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
141
142 GLenum format = alloc->mHal.state.type->getElement()->getComponent().getGLFormat();
143 if (!format) {
144 return;
145 }
146
147 if (!drv->renderTargetID) {
148 glGenRenderbuffers(1, &drv->renderTargetID);
149
150 if (!drv->renderTargetID) {
151 // This should generally not happen
152 LOGE("allocateRenderTarget failed to gen mRenderTargetID");
153 rsc->dumpDebug();
154 return;
155 }
156 glBindRenderbuffer(GL_RENDERBUFFER, drv->renderTargetID);
157 glRenderbufferStorage(GL_RENDERBUFFER, format,
158 alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY);
159 }
160 rsdGLCheckError(rsc, "AllocateRenderTarget");
161}
162
163static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
164 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
165
166 rsAssert(!alloc->mHal.state.type->getDimY());
167 rsAssert(!alloc->mHal.state.type->getDimZ());
168
169 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
170
171 if (!drv->bufferID) {
172 glGenBuffers(1, &drv->bufferID);
173 }
174 if (!drv->bufferID) {
175 LOGE("Upload to buffer object failed");
176 drv->uploadDeferred = true;
177 return;
178 }
179 glBindBuffer(drv->glTarget, drv->bufferID);
180 glBufferData(drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
181 drv->mallocPtr, GL_DYNAMIC_DRAW);
182 glBindBuffer(drv->glTarget, 0);
183 rsdGLCheckError(rsc, "UploadToBufferObject");
184}
185
186bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
187 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
188 if (!drv) {
189 return false;
190 }
191
192 void * ptr = malloc(alloc->mHal.state.type->getSizeBytes());
193 if (!ptr) {
194 free(drv);
195 return false;
196 }
197
198 drv->glTarget = GL_NONE;
199 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
200 if (alloc->mHal.state.hasFaces) {
201 drv->glTarget = GL_TEXTURE_CUBE_MAP;
202 } else {
203 drv->glTarget = GL_TEXTURE_2D;
204 }
205 } else {
206 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
207 drv->glTarget = GL_ARRAY_BUFFER;
208 }
209 }
210
211 alloc->mHal.drvState.mallocPtr = ptr;
212 drv->mallocPtr = (uint8_t *)ptr;
213 alloc->mHal.drv = drv;
214 if (forceZero) {
215 memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
216 }
217
218 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
219 drv->uploadDeferred = true;
220 }
221 return true;
222}
223
224void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
225 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
226
227 if (drv->bufferID) {
228 // Causes a SW crash....
229 //LOGV(" mBufferID %i", mBufferID);
230 //glDeleteBuffers(1, &mBufferID);
231 //mBufferID = 0;
232 }
233 if (drv->textureID) {
234 glDeleteTextures(1, &drv->textureID);
235 drv->textureID = 0;
236 }
237 if (drv->renderTargetID) {
238 glDeleteRenderbuffers(1, &drv->renderTargetID);
239 drv->renderTargetID = 0;
240 }
241
242 if (drv->mallocPtr) {
243 free(drv->mallocPtr);
244 drv->mallocPtr = NULL;
245 }
246 free(drv);
247 alloc->mHal.drv = NULL;
248}
249
250void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
251 const Type *newType, bool zeroNew) {
252 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
253
254 drv->mallocPtr = (uint8_t *)realloc(drv->mallocPtr, newType->getSizeBytes());
255
256 // fixme
257 ((Allocation *)alloc)->mHal.drvState.mallocPtr = drv->mallocPtr;
258
259 const uint32_t oldDimX = alloc->mHal.state.dimensionX;
260 const uint32_t dimX = newType->getDimX();
261
262 if (dimX > oldDimX) {
263 const Element *e = alloc->mHal.state.type->getElement();
264 uint32_t stride = e->getSizeBytes();
265 memset(((uint8_t *)drv->mallocPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
266 }
267}
268
269
270
271void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
272 RsAllocationUsageType src) {
273 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
274
275 if (!drv->uploadDeferred) {
276 return;
277 }
278
279 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
280
281 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
282 UploadToTexture(rsc, alloc);
283 } else {
284 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
285 AllocateRenderTarget(rsc, alloc);
286 }
287 }
288 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
289 UploadToBufferObject(rsc, alloc);
290 }
291
292 drv->uploadDeferred = false;
293}
294
295void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
296 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
297 drv->uploadDeferred = true;
298}
299
300void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
301 uint32_t xoff, uint32_t lod, uint32_t count,
302 const void *data, uint32_t sizeBytes) {
303 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
304
305 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
306 uint8_t * ptr = drv->mallocPtr;
307 ptr += eSize * xoff;
308 uint32_t size = count * eSize;
309
310 if (alloc->mHal.state.hasReferences) {
311 alloc->incRefs(data, count);
312 alloc->decRefs(ptr, count);
313 }
314
315 memcpy(ptr, data, size);
316 drv->uploadDeferred = true;
317}
318
319void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
320 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
321 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
322 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
323
324 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
325 uint32_t lineSize = eSize * w;
326 uint32_t destW = alloc->mHal.state.dimensionX;
327
328 if (drv->mallocPtr) {
329 const uint8_t *src = static_cast<const uint8_t *>(data);
330 uint8_t *dst = drv->mallocPtr;
331 dst += alloc->mHal.state.type->getLODFaceOffset(lod, face, xoff, yoff);
332
333 for (uint32_t line=yoff; line < (yoff+h); line++) {
334 if (alloc->mHal.state.hasReferences) {
335 alloc->incRefs(src, w);
336 alloc->decRefs(dst, w);
337 }
338 memcpy(dst, src, lineSize);
339 src += lineSize;
340 dst += destW * eSize;
341 }
342 drv->uploadDeferred = true;
343 } else {
344 Update2DTexture(alloc, data, xoff, yoff, lod, face, w, h);
345 }
346}
347
348void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
349 uint32_t xoff, uint32_t yoff, uint32_t zoff,
350 uint32_t lod, RsAllocationCubemapFace face,
351 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
352
353}
354
355void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc,
356 uint32_t x,
357 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
358 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
359
360 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
361 uint8_t * ptr = drv->mallocPtr;
362 ptr += eSize * x;
363
364 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
365 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
366
367 if (alloc->mHal.state.hasReferences) {
368 e->incRefs(data);
369 e->decRefs(ptr);
370 }
371
372 memcpy(ptr, data, sizeBytes);
373 drv->uploadDeferred = true;
374}
375
376void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc,
377 uint32_t x, uint32_t y,
378 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
379 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
380
381 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
382 uint8_t * ptr = drv->mallocPtr;
383 ptr += eSize * (x + y * alloc->mHal.state.dimensionX);
384
385 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
386 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
387
388 if (alloc->mHal.state.hasReferences) {
389 e->incRefs(data);
390 e->decRefs(ptr);
391 }
392
393 memcpy(ptr, data, sizeBytes);
394 drv->uploadDeferred = true;
395}
396
397