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