1 /*
2 * Copyright (C) 2013 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 #include "rsdAllocation.h"
18 #include "rsdCore.h"
19
20 #include <android/native_window.h>
21
22 #ifdef RS_COMPATIBILITY_LIB
23 #include "rsCompatibilityLib.h"
24 #else
25 #include "rsdFrameBufferObj.h"
26 #include <vndk/window.h>
27
28 #include <GLES/gl.h>
29 #include <GLES2/gl2.h>
30 #include <GLES/glext.h>
31 #endif
32
33 #include <malloc.h> // for memalign()
34 #include <unistd.h> // for close()
35
36 using android::renderscript::Allocation;
37 using android::renderscript::Context;
38 using android::renderscript::Element;
39 using android::renderscript::Type;
40 using android::renderscript::rs_allocation;
41 using android::renderscript::rsBoxFilter565;
42 using android::renderscript::rsBoxFilter8888;
43 using android::renderscript::rsMax;
44 using android::renderscript::rsRound;
45
46 #ifndef RS_COMPATIBILITY_LIB
47 const static GLenum gFaceOrder[] = {
48 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
49 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
50 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
51 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
52 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
53 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
54 };
55
rsdTypeToGLType(RsDataType t)56 GLenum rsdTypeToGLType(RsDataType t) {
57 switch (t) {
58 case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5;
59 case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1;
60 case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4;
61
62 //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT;
63 case RS_TYPE_FLOAT_32: return GL_FLOAT;
64 case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE;
65 case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT;
66 case RS_TYPE_SIGNED_8: return GL_BYTE;
67 case RS_TYPE_SIGNED_16: return GL_SHORT;
68 default: break;
69 }
70 return 0;
71 }
72
rsdKindToGLFormat(RsDataKind k)73 GLenum rsdKindToGLFormat(RsDataKind k) {
74 switch (k) {
75 case RS_KIND_PIXEL_L: return GL_LUMINANCE;
76 case RS_KIND_PIXEL_A: return GL_ALPHA;
77 case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
78 case RS_KIND_PIXEL_RGB: return GL_RGB;
79 case RS_KIND_PIXEL_RGBA: return GL_RGBA;
80 case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
81 default: break;
82 }
83 return 0;
84 }
85 #endif
86
GetOffsetPtr(const android::renderscript::Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t lod,RsAllocationCubemapFace face)87 uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc,
88 uint32_t xoff, uint32_t yoff, uint32_t zoff,
89 uint32_t lod, RsAllocationCubemapFace face) {
90 uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr;
91 ptr += face * alloc->mHal.drvState.faceOffset;
92 ptr += zoff * alloc->mHal.drvState.lod[lod].dimY * alloc->mHal.drvState.lod[lod].stride;
93 ptr += yoff * alloc->mHal.drvState.lod[lod].stride;
94 ptr += xoff * alloc->mHal.state.elementSizeBytes;
95 return ptr;
96 }
97
98
Update2DTexture(const Context * rsc,const Allocation * alloc,const void * ptr,uint32_t xoff,uint32_t yoff,uint32_t lod,RsAllocationCubemapFace face,uint32_t w,uint32_t h)99 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
100 uint32_t xoff, uint32_t yoff, uint32_t lod,
101 RsAllocationCubemapFace face, uint32_t w, uint32_t h) {
102 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
103 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
104
105 rsAssert(drv->textureID);
106 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
107 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
108 GLenum t = GL_TEXTURE_2D;
109 if (alloc->mHal.state.hasFaces) {
110 t = gFaceOrder[face];
111 }
112 RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
113 #endif
114 }
115
116
117 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
Upload2DTexture(const Context * rsc,const Allocation * alloc,bool isFirstUpload)118 static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
119 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
120
121 RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
122 RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
123
124 uint32_t faceCount = 1;
125 if (alloc->mHal.state.hasFaces) {
126 faceCount = 6;
127 }
128
129 rsdGLCheckError(rsc, "Upload2DTexture 1 ");
130 for (uint32_t face = 0; face < faceCount; face ++) {
131 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
132 const uint8_t *p = GetOffsetPtr(alloc, 0, 0, 0, lod, (RsAllocationCubemapFace)face);
133
134 GLenum t = GL_TEXTURE_2D;
135 if (alloc->mHal.state.hasFaces) {
136 t = gFaceOrder[face];
137 }
138
139 if (isFirstUpload) {
140 RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat,
141 alloc->mHal.state.type->getLODDimX(lod),
142 alloc->mHal.state.type->getLODDimY(lod),
143 0, drv->glFormat, drv->glType, p);
144 } else {
145 RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0,
146 alloc->mHal.state.type->getLODDimX(lod),
147 alloc->mHal.state.type->getLODDimY(lod),
148 drv->glFormat, drv->glType, p);
149 }
150 }
151 }
152
153 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
154 RSD_CALL_GL(glGenerateMipmap, drv->glTarget);
155 }
156 rsdGLCheckError(rsc, "Upload2DTexture");
157 }
158 #endif
159
UploadToTexture(const Context * rsc,const Allocation * alloc)160 static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
161 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
162 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
163
164 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
165 if (!drv->textureID) {
166 RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
167 }
168 return;
169 }
170
171 if (!drv->glType || !drv->glFormat) {
172 return;
173 }
174
175 if (!alloc->mHal.drvState.lod[0].mallocPtr) {
176 return;
177 }
178
179 bool isFirstUpload = false;
180
181 if (!drv->textureID) {
182 RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
183 isFirstUpload = true;
184 }
185
186 Upload2DTexture(rsc, alloc, isFirstUpload);
187
188 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
189 if (alloc->mHal.drvState.lod[0].mallocPtr) {
190 free(alloc->mHal.drvState.lod[0].mallocPtr);
191 alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
192 }
193 }
194 rsdGLCheckError(rsc, "UploadToTexture");
195 #endif
196 }
197
AllocateRenderTarget(const Context * rsc,const Allocation * alloc)198 static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
199 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
200 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
201
202 if (!drv->glFormat) {
203 return;
204 }
205
206 if (!drv->renderTargetID) {
207 RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID);
208
209 if (!drv->renderTargetID) {
210 // This should generally not happen
211 ALOGE("allocateRenderTarget failed to gen mRenderTargetID");
212 rsc->dumpDebug();
213 return;
214 }
215 RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID);
216 RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat,
217 alloc->mHal.drvState.lod[0].dimX, alloc->mHal.drvState.lod[0].dimY);
218 }
219 rsdGLCheckError(rsc, "AllocateRenderTarget");
220 #endif
221 }
222
UploadToBufferObject(const Context * rsc,const Allocation * alloc)223 static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
224 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
225 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
226
227 rsAssert(!alloc->mHal.state.type->getDimY());
228 rsAssert(!alloc->mHal.state.type->getDimZ());
229
230 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
231
232 if (!drv->bufferID) {
233 RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID);
234 }
235 if (!drv->bufferID) {
236 ALOGE("Upload to buffer object failed");
237 drv->uploadDeferred = true;
238 return;
239 }
240 RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID);
241 RSD_CALL_GL(glBufferData, drv->glTarget,
242 alloc->mHal.state.type->getPackedSizeBytes(),
243 alloc->mHal.drvState.lod[0].mallocPtr, GL_DYNAMIC_DRAW);
244 RSD_CALL_GL(glBindBuffer, drv->glTarget, 0);
245 rsdGLCheckError(rsc, "UploadToBufferObject");
246 #endif
247 }
248
249
DeriveYUVLayout(int yuv,Allocation::Hal::DrvState * state)250 static size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) {
251 #ifndef RS_COMPATIBILITY_LIB
252 // For the flexible YCbCr format, layout is initialized during call to
253 // Allocation::ioReceive. Return early and avoid clobberring any
254 // pre-existing layout.
255 if (yuv == RS_YUV_420_888) {
256 return 0;
257 }
258 #endif
259
260 // YUV only supports basic 2d
261 // so we can stash the plane pointers in the mipmap levels.
262 size_t uvSize = 0;
263 state->lod[1].dimX = state->lod[0].dimX / 2;
264 state->lod[1].dimY = state->lod[0].dimY / 2;
265 state->lod[2].dimX = state->lod[0].dimX / 2;
266 state->lod[2].dimY = state->lod[0].dimY / 2;
267 state->yuv.shift = 1;
268 state->yuv.step = 1;
269 state->lodCount = 3;
270
271 switch(yuv) {
272 case RS_YUV_YV12:
273 state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16);
274 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
275 (state->lod[0].stride * state->lod[0].dimY);
276 uvSize += state->lod[2].stride * state->lod[2].dimY;
277
278 state->lod[1].stride = state->lod[2].stride;
279 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) +
280 (state->lod[2].stride * state->lod[2].dimY);
281 uvSize += state->lod[1].stride * state->lod[2].dimY;
282 break;
283 case RS_YUV_NV21:
284 //state->lod[1].dimX = state->lod[0].dimX;
285 state->lod[1].stride = state->lod[0].stride;
286 state->lod[2].stride = state->lod[0].stride;
287 state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
288 (state->lod[0].stride * state->lod[0].dimY);
289 state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1;
290 uvSize += state->lod[1].stride * state->lod[1].dimY;
291 state->yuv.step = 2;
292 break;
293 default:
294 rsAssert(0);
295 }
296 return uvSize;
297 }
298
AllocationBuildPointerTable(const Context * rsc,const Allocation * alloc,const Type * type,uint8_t * ptr,size_t requiredAlignment)299 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
300 const Type *type, uint8_t *ptr, size_t requiredAlignment) {
301 alloc->mHal.drvState.lod[0].dimX = type->getDimX();
302 alloc->mHal.drvState.lod[0].dimY = type->getDimY();
303 alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
304 alloc->mHal.drvState.lod[0].mallocPtr = 0;
305 // Stride needs to be aligned to a boundary defined by requiredAlignment!
306 size_t stride = alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
307 alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment);
308 alloc->mHal.drvState.lodCount = type->getLODCount();
309 alloc->mHal.drvState.faceCount = type->getDimFaces();
310
311 size_t offsets[Allocation::MAX_LOD];
312 memset(offsets, 0, sizeof(offsets));
313
314 size_t o = alloc->mHal.drvState.lod[0].stride * rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) *
315 rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u);
316 if (alloc->mHal.state.yuv) {
317 o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
318
319 for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) {
320 offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr;
321 }
322 } else if(alloc->mHal.drvState.lodCount > 1) {
323 uint32_t tx = alloc->mHal.drvState.lod[0].dimX;
324 uint32_t ty = alloc->mHal.drvState.lod[0].dimY;
325 uint32_t tz = alloc->mHal.drvState.lod[0].dimZ;
326 for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
327 alloc->mHal.drvState.lod[lod].dimX = tx;
328 alloc->mHal.drvState.lod[lod].dimY = ty;
329 alloc->mHal.drvState.lod[lod].dimZ = tz;
330 alloc->mHal.drvState.lod[lod].stride =
331 rsRound(tx * type->getElementSizeBytes(), requiredAlignment);
332 offsets[lod] = o;
333 o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
334 if (tx > 1) tx >>= 1;
335 if (ty > 1) ty >>= 1;
336 if (tz > 1) tz >>= 1;
337 }
338 }
339
340 alloc->mHal.drvState.faceOffset = o;
341
342 alloc->mHal.drvState.lod[0].mallocPtr = ptr;
343 for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
344 alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod];
345 }
346
347 size_t allocSize = alloc->mHal.drvState.faceOffset;
348 if(alloc->mHal.drvState.faceCount) {
349 allocSize *= 6;
350 }
351
352 return allocSize;
353 }
354
AllocationBuildPointerTable(const Context * rsc,const Allocation * alloc,const Type * type,uint8_t * ptr)355 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
356 const Type *type, uint8_t *ptr) {
357 return AllocationBuildPointerTable(rsc, alloc, type, ptr, Allocation::kMinimumRSAlignment);
358 }
359
allocAlignedMemory(size_t allocSize,bool forceZero,size_t requiredAlignment)360 static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero, size_t requiredAlignment) {
361 // We align all allocations to a boundary defined by requiredAlignment.
362 uint8_t* ptr = (uint8_t *)memalign(requiredAlignment, allocSize);
363 if (!ptr) {
364 return nullptr;
365 }
366 if (forceZero) {
367 memset(ptr, 0, allocSize);
368 }
369 return ptr;
370 }
371
rsdAllocationInitStrided(const Context * rsc,Allocation * alloc,bool forceZero,size_t requiredAlignment)372 bool rsdAllocationInitStrided(const Context *rsc, Allocation *alloc, bool forceZero, size_t requiredAlignment) {
373 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
374 if (!drv) {
375 return false;
376 }
377 alloc->mHal.drv = drv;
378
379 // Check if requiredAlignment is power of 2, also requiredAlignment should be larger or equal than kMinimumRSAlignment.
380 if ((requiredAlignment & (requiredAlignment-1)) != 0 || requiredAlignment < Allocation::kMinimumRSAlignment) {
381 ALOGE("requiredAlignment must be power of 2");
382 return false;
383 }
384 // Calculate the object size.
385 size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), nullptr, requiredAlignment);
386
387 uint8_t * ptr = nullptr;
388 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
389
390 } else if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
391 // Allocation is allocated when the surface is created
392 // in getSurface
393 #ifdef RS_COMPATIBILITY_LIB
394 } else if (alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT | RS_ALLOCATION_USAGE_SHARED)) {
395 if (alloc->mHal.state.userProvidedPtr == nullptr) {
396 ALOGE("User-backed buffer pointer cannot be null");
397 return false;
398 }
399 if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
400 ALOGE("User-allocated buffers must not have multiple faces or LODs");
401 return false;
402 }
403
404 drv->useUserProvidedPtr = true;
405 ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
406 #endif
407 } else if (alloc->mHal.state.userProvidedPtr != nullptr) {
408 // user-provided allocation
409 // limitations: no faces, no LOD, USAGE_SCRIPT or SCRIPT+TEXTURE only
410 if (!(alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED) ||
411 alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE))) {
412 ALOGE("Can't use user-allocated buffers if usage is not USAGE_SCRIPT | USAGE_SHARED or USAGE_SCRIPT | USAGE_SHARED | USAGE_GRAPHICS_TEXTURE");
413 return false;
414 }
415 if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
416 ALOGE("User-allocated buffers must not have multiple faces or LODs");
417 return false;
418 }
419
420 // rows must be aligned based on requiredAlignment.
421 // validate that here, otherwise fall back to not use the user-backed allocation
422 if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % requiredAlignment) != 0) {
423 ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation");
424 drv->useUserProvidedPtr = false;
425
426 ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment);
427 if (!ptr) {
428 alloc->mHal.drv = nullptr;
429 free(drv);
430 return false;
431 }
432
433 } else {
434 drv->useUserProvidedPtr = true;
435 ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
436 }
437 } else {
438 ptr = allocAlignedMemory(allocSize, forceZero, requiredAlignment);
439 if (!ptr) {
440 alloc->mHal.drv = nullptr;
441 free(drv);
442 return false;
443 }
444 }
445 // Build the pointer tables
446 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr, requiredAlignment);
447 if(allocSize != verifySize) {
448 rsAssert(!"Size mismatch");
449 }
450
451 drv->glTarget = GL_NONE;
452 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
453 if (alloc->mHal.state.hasFaces) {
454 drv->glTarget = GL_TEXTURE_CUBE_MAP;
455 } else {
456 drv->glTarget = GL_TEXTURE_2D;
457 }
458 } else {
459 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
460 drv->glTarget = GL_ARRAY_BUFFER;
461 }
462 }
463
464 #ifndef RS_COMPATIBILITY_LIB
465 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
466 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
467 #else
468 drv->glType = 0;
469 drv->glFormat = 0;
470 #endif
471
472 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
473 drv->uploadDeferred = true;
474 }
475
476 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
477 drv->readBackFBO = nullptr;
478 #endif
479
480 // fill out the initial state of the buffer if we couldn't use the user-provided ptr and USAGE_SHARED was accepted
481 if ((alloc->mHal.state.userProvidedPtr != 0) && (drv->useUserProvidedPtr == false)) {
482 rsdAllocationData2D(rsc, alloc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, alloc->getType()->getDimX(), alloc->getType()->getDimY(), alloc->mHal.state.userProvidedPtr, allocSize, 0);
483 }
484
485
486 #ifdef RS_FIND_OFFSETS
487 ALOGE("pointer for allocation: %p", alloc);
488 ALOGE("pointer for allocation.drv: %p", &alloc->mHal.drv);
489 #endif
490
491
492 return true;
493 }
494
rsdAllocationInit(const Context * rsc,Allocation * alloc,bool forceZero)495 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
496 return rsdAllocationInitStrided(rsc, alloc, forceZero, Allocation::kMinimumRSAlignment);
497 }
498
rsdAllocationAdapterOffset(const Context * rsc,const Allocation * alloc)499 void rsdAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
500 //ALOGE("rsdAllocationAdapterOffset");
501
502 // Get a base pointer to the new LOD
503 const Allocation *base = alloc->mHal.state.baseAlloc;
504 const Type *type = alloc->mHal.state.type;
505 if (base == nullptr) {
506 return;
507 }
508
509 //ALOGE("rsdAllocationAdapterOffset %p %p", ptrA, ptrB);
510 //ALOGE("rsdAllocationAdapterOffset lodCount %i", alloc->mHal.drvState.lodCount);
511
512 const int lodBias = alloc->mHal.state.originLOD;
513 uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
514 for (uint32_t lod=0; lod < lodCount; lod++) {
515 alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
516 alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(alloc,
517 alloc->mHal.state.originX, alloc->mHal.state.originY, alloc->mHal.state.originZ,
518 lodBias, (RsAllocationCubemapFace)alloc->mHal.state.originFace);
519 }
520 }
521
rsdAllocationAdapterInit(const Context * rsc,Allocation * alloc)522 bool rsdAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
523 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
524 if (!drv) {
525 return false;
526 }
527 alloc->mHal.drv = drv;
528
529 // We need to build an allocation that looks like a subset of the parent allocation
530 rsdAllocationAdapterOffset(rsc, alloc);
531
532 return true;
533 }
534
rsdAllocationDestroy(const Context * rsc,Allocation * alloc)535 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
536 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
537
538 if (alloc->mHal.state.baseAlloc == nullptr) {
539 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
540 if (drv->bufferID) {
541 // Causes a SW crash....
542 //ALOGV(" mBufferID %i", mBufferID);
543 //glDeleteBuffers(1, &mBufferID);
544 //mBufferID = 0;
545 }
546 if (drv->textureID) {
547 RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
548 drv->textureID = 0;
549 }
550 if (drv->renderTargetID) {
551 RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
552 drv->renderTargetID = 0;
553 }
554 #endif
555
556 if (alloc->mHal.drvState.lod[0].mallocPtr) {
557 // don't free user-allocated ptrs or IO_OUTPUT buffers
558 if (!(drv->useUserProvidedPtr) &&
559 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) &&
560 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
561 free(alloc->mHal.drvState.lod[0].mallocPtr);
562 }
563 alloc->mHal.drvState.lod[0].mallocPtr = nullptr;
564 }
565
566 #ifndef RS_COMPATIBILITY_LIB
567 #ifndef RS_VENDOR_LIB
568 if (drv->readBackFBO != nullptr) {
569 delete drv->readBackFBO;
570 drv->readBackFBO = nullptr;
571 }
572 #endif
573 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
574 (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
575 ANativeWindow *nw = drv->wndSurface;
576 if (nw) {
577 //If we have an attached surface, need to release it.
578 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer);
579 int fenceID = -1;
580 AHardwareBuffer_unlock(ahwb, &fenceID);
581 ANativeWindow_cancelBuffer(nw, drv->wndBuffer, fenceID);
582 ANativeWindow_release(nw);
583 drv->wndSurface = nullptr;
584 drv->wndBuffer = nullptr;
585 }
586 }
587 #endif
588 }
589
590 free(drv);
591 alloc->mHal.drv = nullptr;
592 }
593
rsdAllocationResize(const Context * rsc,const Allocation * alloc,const Type * newType,bool zeroNew)594 void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
595 const Type *newType, bool zeroNew) {
596 const uint32_t oldDimX = alloc->mHal.drvState.lod[0].dimX;
597 const uint32_t dimX = newType->getDimX();
598
599 // can't resize Allocations with user-allocated buffers
600 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
601 ALOGE("Resize cannot be called on a USAGE_SHARED allocation");
602 return;
603 }
604 void * oldPtr = alloc->mHal.drvState.lod[0].mallocPtr;
605 // Calculate the object size
606 size_t s = AllocationBuildPointerTable(rsc, alloc, newType, nullptr);
607 uint8_t *ptr = (uint8_t *)realloc(oldPtr, s);
608 // Build the relative pointer tables.
609 size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr);
610 if(s != verifySize) {
611 rsAssert(!"Size mismatch");
612 }
613
614
615 if (dimX > oldDimX) {
616 size_t stride = alloc->mHal.state.elementSizeBytes;
617 memset(((uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr) + stride * oldDimX,
618 0, stride * (dimX - oldDimX));
619 }
620 }
621
rsdAllocationSyncFromFBO(const Context * rsc,const Allocation * alloc)622 static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) {
623 #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
624 if (!alloc->getIsScript()) {
625 return; // nothing to sync
626 }
627
628 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
629 RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer;
630
631 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
632 if (!drv->textureID && !drv->renderTargetID) {
633 return; // nothing was rendered here yet, so nothing to sync
634 }
635 if (drv->readBackFBO == nullptr) {
636 drv->readBackFBO = new RsdFrameBufferObj();
637 drv->readBackFBO->setColorTarget(drv, 0);
638 drv->readBackFBO->setDimensions(alloc->getType()->getDimX(),
639 alloc->getType()->getDimY());
640 }
641
642 // Bind the framebuffer object so we can read back from it
643 drv->readBackFBO->setActive(rsc);
644
645 // Do the readback
646 RSD_CALL_GL(glReadPixels, 0, 0, alloc->mHal.drvState.lod[0].dimX,
647 alloc->mHal.drvState.lod[0].dimY,
648 drv->glFormat, drv->glType, alloc->mHal.drvState.lod[0].mallocPtr);
649
650 // Revert framebuffer to its original
651 lastFbo->setActive(rsc);
652 #endif
653 }
654
655
rsdAllocationSyncAll(const Context * rsc,const Allocation * alloc,RsAllocationUsageType src)656 void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
657 RsAllocationUsageType src) {
658 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
659
660 if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
661 if(!alloc->getIsRenderTarget()) {
662 rsc->setError(RS_ERROR_FATAL_DRIVER,
663 "Attempting to sync allocation from render target, "
664 "for non-render target allocation");
665 } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) {
666 rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA"
667 "render target");
668 } else {
669 rsdAllocationSyncFromFBO(rsc, alloc);
670 }
671 return;
672 }
673
674 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT || src == RS_ALLOCATION_USAGE_SHARED);
675
676 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
677 UploadToTexture(rsc, alloc);
678 } else {
679 if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) &&
680 !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
681 AllocateRenderTarget(rsc, alloc);
682 }
683 }
684 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
685 UploadToBufferObject(rsc, alloc);
686 }
687
688 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
689
690 if (src == RS_ALLOCATION_USAGE_SHARED) {
691 // just a memory fence for the CPU driver
692 // vendor drivers probably want to flush any dirty cachelines for
693 // this particular Allocation
694 __sync_synchronize();
695 }
696 }
697
698 drv->uploadDeferred = false;
699 }
700
rsdAllocationMarkDirty(const Context * rsc,const Allocation * alloc)701 void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
702 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
703 drv->uploadDeferred = true;
704 }
705
706 #ifndef RS_COMPATIBILITY_LIB
IoGetBuffer(const Context * rsc,Allocation * alloc,ANativeWindow * nw)707 static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
708 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
709 // Must lock the whole surface
710 int fenceID = -1;
711 int r = ANativeWindow_dequeueBuffer(nw, &drv->wndBuffer, &fenceID);
712 if (r) {
713 rsc->setError(RS_ERROR_DRIVER, "Error dequeueing IO output buffer.");
714 close(fenceID);
715 return false;
716 }
717
718 void *dst = nullptr;
719 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer);
720 r = AHardwareBuffer_lock(ahwb, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
721 fenceID, NULL, &dst);
722 if (r) {
723 rsc->setError(RS_ERROR_DRIVER, "Error Locking IO output buffer.");
724 return false;
725 }
726 alloc->mHal.drvState.lod[0].mallocPtr = dst;
727 alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
728 rsAssert((alloc->mHal.drvState.lod[0].stride & 0xf) == 0);
729
730 return true;
731 }
732 #endif
733
rsdAllocationSetSurface(const Context * rsc,Allocation * alloc,ANativeWindow * nw)734 void rsdAllocationSetSurface(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
735 #ifndef RS_COMPATIBILITY_LIB
736 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
737
738 // Cleanup old surface if there is one.
739 if (drv->wndSurface) {
740 ANativeWindow *old = drv->wndSurface;
741 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer);
742 int fenceID = -1;
743 int32_t r = AHardwareBuffer_unlock(ahwb, &fenceID);
744 if (r) {
745 rsc->setError(RS_ERROR_DRIVER, "Error unlocking output buffer.");
746 close(fenceID);
747 return;
748 }
749 r = ANativeWindow_cancelBuffer(old, drv->wndBuffer, fenceID);
750 if (r) {
751 rsc->setError(RS_ERROR_DRIVER, "Error canceling output buffer.");
752 return;
753 }
754 ANativeWindow_release(old);
755 drv->wndSurface = nullptr;
756 drv->wndBuffer = nullptr;
757 }
758
759 if (nw) {
760 int32_t r = ANativeWindow_setBuffersGeometry(nw, alloc->mHal.drvState.lod[0].dimX,
761 alloc->mHal.drvState.lod[0].dimY,
762 WINDOW_FORMAT_RGBA_8888);
763 if (r) {
764 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer geometry.");
765 return;
766 }
767
768 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
769 r = ANativeWindow_setUsage(nw,
770 AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN);
771 if (r) {
772 rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
773 return;
774 }
775 }
776
777 IoGetBuffer(rsc, alloc, nw);
778 drv->wndSurface = nw;
779 }
780
781 return;
782 #endif
783 }
784
rsdAllocationIoSend(const Context * rsc,Allocation * alloc)785 void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) {
786 #ifndef RS_COMPATIBILITY_LIB
787 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
788 ANativeWindow *nw = drv->wndSurface;
789 #ifndef RS_VENDOR_LIB
790 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
791 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
792 RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
793 return;
794 }
795 #endif
796 if (nw) {
797 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
798 AHardwareBuffer* ahwb = ANativeWindowBuffer_getHardwareBuffer(drv->wndBuffer);
799 int fenceID = -1;
800 int32_t r = AHardwareBuffer_unlock(ahwb, &fenceID);
801 if (r) {
802 rsc->setError(RS_ERROR_DRIVER, "Error unlock output buffer.");
803 close(fenceID);
804 return;
805 }
806 r = ANativeWindow_queueBuffer(nw, drv->wndBuffer, fenceID);
807 if (r) {
808 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer.");
809 return;
810 }
811 drv->wndBuffer = nullptr;
812 IoGetBuffer(rsc, alloc, nw);
813 }
814 } else {
815 rsc->setError(RS_ERROR_DRIVER, "Sent IO buffer with no attached surface.");
816 return;
817 }
818 #endif
819 }
820
rsdAllocationIoReceive(const Context * rsc,Allocation * alloc)821 void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
822 if (alloc->mHal.state.yuv) {
823 DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
824 }
825 }
826
827
rsdAllocationData1D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t lod,size_t count,const void * data,size_t sizeBytes)828 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
829 uint32_t xoff, uint32_t lod, size_t count,
830 const void *data, size_t sizeBytes) {
831 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
832
833 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
834 uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
835 size_t size = count * eSize;
836 if (ptr != data) {
837 // Skip the copy if we are the same allocation. This can arise from
838 // our Bitmap optimization, where we share the same storage.
839 if (alloc->mHal.state.hasReferences) {
840 alloc->incRefs(data, count);
841 alloc->decRefs(ptr, count);
842 }
843 memcpy(ptr, data, size);
844 }
845 drv->uploadDeferred = true;
846 }
847
rsdAllocationData2D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t lod,RsAllocationCubemapFace face,uint32_t w,uint32_t h,const void * data,size_t sizeBytes,size_t stride)848 void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
849 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
850 uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
851 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
852
853 size_t eSize = alloc->mHal.state.elementSizeBytes;
854 size_t lineSize = eSize * w;
855 if (!stride) {
856 stride = lineSize;
857 }
858
859 if (alloc->mHal.drvState.lod[0].mallocPtr) {
860 const uint8_t *src = static_cast<const uint8_t *>(data);
861 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
862 if (dst == src) {
863 // Skip the copy if we are the same allocation. This can arise from
864 // our Bitmap optimization, where we share the same storage.
865 drv->uploadDeferred = true;
866 return;
867 }
868
869 for (uint32_t line=yoff; line < (yoff+h); line++) {
870 if (alloc->mHal.state.hasReferences) {
871 alloc->incRefs(src, w);
872 alloc->decRefs(dst, w);
873 }
874 memcpy(dst, src, lineSize);
875 src += stride;
876 dst += alloc->mHal.drvState.lod[lod].stride;
877 }
878 if (alloc->mHal.state.yuv) {
879 size_t clineSize = lineSize;
880 int lod = 1;
881 int maxLod = 2;
882 if (alloc->mHal.state.yuv == RS_YUV_YV12) {
883 maxLod = 3;
884 clineSize >>= 1;
885 } else if (alloc->mHal.state.yuv == RS_YUV_NV21) {
886 lod = 2;
887 maxLod = 3;
888 }
889
890 while (lod < maxLod) {
891 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
892
893 for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) {
894 memcpy(dst, src, clineSize);
895 // When copying from an array to an Allocation, the src pointer
896 // to the array should just move by the number of bytes copied.
897 src += clineSize;
898 dst += alloc->mHal.drvState.lod[lod].stride;
899 }
900 lod++;
901 }
902
903 }
904 drv->uploadDeferred = true;
905 } else {
906 Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
907 }
908 }
909
rsdAllocationData3D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t lod,uint32_t w,uint32_t h,uint32_t d,const void * data,size_t sizeBytes,size_t stride)910 void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
911 uint32_t xoff, uint32_t yoff, uint32_t zoff,
912 uint32_t lod,
913 uint32_t w, uint32_t h, uint32_t d, const void *data,
914 size_t sizeBytes, size_t stride) {
915 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
916
917 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
918 uint32_t lineSize = eSize * w;
919 if (!stride) {
920 stride = lineSize;
921 }
922
923 if (alloc->mHal.drvState.lod[0].mallocPtr) {
924 const uint8_t *src = static_cast<const uint8_t *>(data);
925 for (uint32_t z = zoff; z < (d + zoff); z++) {
926 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
927 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
928 if (dst == src) {
929 // Skip the copy if we are the same allocation. This can arise from
930 // our Bitmap optimization, where we share the same storage.
931 drv->uploadDeferred = true;
932 return;
933 }
934
935 for (uint32_t line=yoff; line < (yoff+h); line++) {
936 if (alloc->mHal.state.hasReferences) {
937 alloc->incRefs(src, w);
938 alloc->decRefs(dst, w);
939 }
940 memcpy(dst, src, lineSize);
941 src += stride;
942 dst += alloc->mHal.drvState.lod[lod].stride;
943 }
944 }
945 drv->uploadDeferred = true;
946 }
947 }
948
rsdAllocationRead1D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t lod,size_t count,void * data,size_t sizeBytes)949 void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc,
950 uint32_t xoff, uint32_t lod, size_t count,
951 void *data, size_t sizeBytes) {
952 const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
953 const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
954 if (data != ptr) {
955 // Skip the copy if we are the same allocation. This can arise from
956 // our Bitmap optimization, where we share the same storage.
957 memcpy(data, ptr, count * eSize);
958 }
959 }
960
rsdAllocationRead2D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t lod,RsAllocationCubemapFace face,uint32_t w,uint32_t h,void * data,size_t sizeBytes,size_t stride)961 void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc,
962 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
963 uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) {
964 size_t eSize = alloc->mHal.state.elementSizeBytes;
965 size_t lineSize = eSize * w;
966 if (!stride) {
967 stride = lineSize;
968 }
969
970 if (alloc->mHal.drvState.lod[0].mallocPtr) {
971 uint8_t *dst = static_cast<uint8_t *>(data);
972 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
973 if (dst == src) {
974 // Skip the copy if we are the same allocation. This can arise from
975 // our Bitmap optimization, where we share the same storage.
976 return;
977 }
978
979 for (uint32_t line=yoff; line < (yoff+h); line++) {
980 memcpy(dst, src, lineSize);
981 dst += stride;
982 src += alloc->mHal.drvState.lod[lod].stride;
983 }
984 } else {
985 ALOGE("Add code to readback from non-script memory");
986 }
987 }
988
989
rsdAllocationRead3D(const Context * rsc,const Allocation * alloc,uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t lod,uint32_t w,uint32_t h,uint32_t d,void * data,size_t sizeBytes,size_t stride)990 void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc,
991 uint32_t xoff, uint32_t yoff, uint32_t zoff,
992 uint32_t lod,
993 uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) {
994 uint32_t eSize = alloc->mHal.state.elementSizeBytes;
995 uint32_t lineSize = eSize * w;
996 if (!stride) {
997 stride = lineSize;
998 }
999
1000 if (alloc->mHal.drvState.lod[0].mallocPtr) {
1001 uint8_t *dst = static_cast<uint8_t *>(data);
1002 for (uint32_t z = zoff; z < (d + zoff); z++) {
1003 const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
1004 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1005 if (dst == src) {
1006 // Skip the copy if we are the same allocation. This can arise from
1007 // our Bitmap optimization, where we share the same storage.
1008 return;
1009 }
1010
1011 for (uint32_t line=yoff; line < (yoff+h); line++) {
1012 memcpy(dst, src, lineSize);
1013 dst += stride;
1014 src += alloc->mHal.drvState.lod[lod].stride;
1015 }
1016 }
1017 }
1018 }
1019
rsdAllocationLock1D(const android::renderscript::Context * rsc,const android::renderscript::Allocation * alloc)1020 void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
1021 const android::renderscript::Allocation *alloc) {
1022 return alloc->mHal.drvState.lod[0].mallocPtr;
1023 }
1024
rsdAllocationUnlock1D(const android::renderscript::Context * rsc,const android::renderscript::Allocation * alloc)1025 void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
1026 const android::renderscript::Allocation *alloc) {
1027
1028 }
1029
rsdAllocationData1D_alloc(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstLod,size_t count,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcLod)1030 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
1031 const android::renderscript::Allocation *dstAlloc,
1032 uint32_t dstXoff, uint32_t dstLod, size_t count,
1033 const android::renderscript::Allocation *srcAlloc,
1034 uint32_t srcXoff, uint32_t srcLod) {
1035 }
1036
1037
rsdAllocationData2D_alloc_script(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstLod,RsAllocationCubemapFace dstFace,uint32_t w,uint32_t h,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcLod,RsAllocationCubemapFace srcFace)1038 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
1039 const android::renderscript::Allocation *dstAlloc,
1040 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
1041 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
1042 const android::renderscript::Allocation *srcAlloc,
1043 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
1044 RsAllocationCubemapFace srcFace) {
1045 size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
1046 for (uint32_t i = 0; i < h; i ++) {
1047 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
1048 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
1049 memcpy(dstPtr, srcPtr, w * elementSize);
1050
1051 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
1052 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
1053 }
1054 }
1055
rsdAllocationData3D_alloc_script(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstZoff,uint32_t dstLod,uint32_t w,uint32_t h,uint32_t d,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcZoff,uint32_t srcLod)1056 void rsdAllocationData3D_alloc_script(const android::renderscript::Context *rsc,
1057 const android::renderscript::Allocation *dstAlloc,
1058 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod,
1059 uint32_t w, uint32_t h, uint32_t d,
1060 const android::renderscript::Allocation *srcAlloc,
1061 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod) {
1062 uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
1063 for (uint32_t j = 0; j < d; j++) {
1064 for (uint32_t i = 0; i < h; i ++) {
1065 uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j,
1066 dstLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1067 uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j,
1068 srcLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1069 memcpy(dstPtr, srcPtr, w * elementSize);
1070
1071 //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
1072 // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
1073 }
1074 }
1075 }
1076
rsdAllocationData2D_alloc(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstLod,RsAllocationCubemapFace dstFace,uint32_t w,uint32_t h,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcLod,RsAllocationCubemapFace srcFace)1077 void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
1078 const android::renderscript::Allocation *dstAlloc,
1079 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
1080 RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
1081 const android::renderscript::Allocation *srcAlloc,
1082 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
1083 RsAllocationCubemapFace srcFace) {
1084 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
1085 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
1086 "yet implemented.");
1087 return;
1088 }
1089 rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff,
1090 dstLod, dstFace, w, h, srcAlloc,
1091 srcXoff, srcYoff, srcLod, srcFace);
1092 }
1093
rsdAllocationData3D_alloc(const android::renderscript::Context * rsc,const android::renderscript::Allocation * dstAlloc,uint32_t dstXoff,uint32_t dstYoff,uint32_t dstZoff,uint32_t dstLod,uint32_t w,uint32_t h,uint32_t d,const android::renderscript::Allocation * srcAlloc,uint32_t srcXoff,uint32_t srcYoff,uint32_t srcZoff,uint32_t srcLod)1094 void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
1095 const android::renderscript::Allocation *dstAlloc,
1096 uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
1097 uint32_t dstLod,
1098 uint32_t w, uint32_t h, uint32_t d,
1099 const android::renderscript::Allocation *srcAlloc,
1100 uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
1101 uint32_t srcLod) {
1102 if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
1103 rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
1104 "yet implemented.");
1105 return;
1106 }
1107 rsdAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
1108 dstLod, w, h, d, srcAlloc,
1109 srcXoff, srcYoff, srcZoff, srcLod);
1110 }
1111
rsdAllocationElementData(const Context * rsc,const Allocation * alloc,uint32_t x,uint32_t y,uint32_t z,const void * data,uint32_t cIdx,size_t sizeBytes)1112 void rsdAllocationElementData(const Context *rsc, const Allocation *alloc,
1113 uint32_t x, uint32_t y, uint32_t z,
1114 const void *data, uint32_t cIdx, size_t sizeBytes) {
1115 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
1116
1117 uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1118
1119 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
1120 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
1121
1122 if (alloc->mHal.state.hasReferences) {
1123 e->incRefs(data);
1124 e->decRefs(ptr);
1125 }
1126
1127 memcpy(ptr, data, sizeBytes);
1128 drv->uploadDeferred = true;
1129 }
1130
rsdAllocationElementRead(const Context * rsc,const Allocation * alloc,uint32_t x,uint32_t y,uint32_t z,void * data,uint32_t cIdx,size_t sizeBytes)1131 void rsdAllocationElementRead(const Context *rsc, const Allocation *alloc,
1132 uint32_t x, uint32_t y, uint32_t z,
1133 void *data, uint32_t cIdx, size_t sizeBytes) {
1134 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
1135
1136 uint8_t * ptr = GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
1137
1138 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
1139 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
1140
1141 memcpy(data, ptr, sizeBytes);
1142 }
1143
mip565(const Allocation * alloc,int lod,RsAllocationCubemapFace face)1144 static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1145 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1146 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1147
1148 for (uint32_t y=0; y < h; y++) {
1149 uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1150 const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2, lod, face);
1151 const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2+1, lod, face);
1152
1153 for (uint32_t x=0; x < w; x++) {
1154 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
1155 oPtr ++;
1156 i1 += 2;
1157 i2 += 2;
1158 }
1159 }
1160 }
1161
mip8888(const Allocation * alloc,int lod,RsAllocationCubemapFace face)1162 static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1163 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1164 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1165
1166 for (uint32_t y=0; y < h; y++) {
1167 uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1168 const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
1169 const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
1170
1171 for (uint32_t x=0; x < w; x++) {
1172 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
1173 oPtr ++;
1174 i1 += 2;
1175 i2 += 2;
1176 }
1177 }
1178 }
1179
mip8(const Allocation * alloc,int lod,RsAllocationCubemapFace face)1180 static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
1181 uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
1182 uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
1183
1184 for (uint32_t y=0; y < h; y++) {
1185 uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
1186 const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
1187 const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
1188
1189 for (uint32_t x=0; x < w; x++) {
1190 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
1191 oPtr ++;
1192 i1 += 2;
1193 i2 += 2;
1194 }
1195 }
1196 }
1197
rsdAllocationGenerateMipmaps(const Context * rsc,const Allocation * alloc)1198 void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) {
1199 if(!alloc->mHal.drvState.lod[0].mallocPtr) {
1200 return;
1201 }
1202 uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
1203 for (uint32_t face = 0; face < numFaces; face ++) {
1204 for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) {
1205 switch (alloc->getType()->getElement()->getSizeBits()) {
1206 case 32:
1207 mip8888(alloc, lod, (RsAllocationCubemapFace)face);
1208 break;
1209 case 16:
1210 mip565(alloc, lod, (RsAllocationCubemapFace)face);
1211 break;
1212 case 8:
1213 mip8(alloc, lod, (RsAllocationCubemapFace)face);
1214 break;
1215 }
1216 }
1217 }
1218 }
1219
rsdAllocationGrallocBits(const android::renderscript::Context * rsc,android::renderscript::Allocation * alloc)1220 uint32_t rsdAllocationGrallocBits(const android::renderscript::Context *rsc,
1221 android::renderscript::Allocation *alloc)
1222 {
1223 return 0;
1224 }
1225
rsdAllocationUpdateCachedObject(const Context * rsc,const Allocation * alloc,rs_allocation * obj)1226 void rsdAllocationUpdateCachedObject(const Context *rsc,
1227 const Allocation *alloc,
1228 rs_allocation *obj)
1229 {
1230 obj->p = alloc;
1231 #ifdef __LP64__
1232 obj->unused1 = nullptr;
1233 obj->unused2 = nullptr;
1234 obj->unused3 = nullptr;
1235 #endif
1236 }
1237