rsovRuntimeStubs.cpp revision 700e68883c4324c15b380ff6724249f39d4f498c
1/*
2 * Copyright (C) 2011-2012 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 <time.h>
18
19#include "rsContext.h"
20#include "rsElement.h"
21#include "rsMatrix2x2.h"
22#include "rsMatrix3x3.h"
23#include "rsMatrix4x4.h"
24#include "rsRuntime.h"
25#include "rsScriptC.h"
26#include "rsType.h"
27#include "rsovAllocation.h"
28#include "rsovCore.h"
29#include "rsovScript.h"
30
31using namespace android;
32using namespace android::renderscript;
33
34typedef __fp16 half;
35typedef half half2 __attribute__((ext_vector_type(2)));
36typedef half half3 __attribute__((ext_vector_type(3)));
37typedef half half4 __attribute__((ext_vector_type(4)));
38
39typedef float float2 __attribute__((ext_vector_type(2)));
40typedef float float3 __attribute__((ext_vector_type(3)));
41typedef float float4 __attribute__((ext_vector_type(4)));
42typedef double double2 __attribute__((ext_vector_type(2)));
43typedef double double3 __attribute__((ext_vector_type(3)));
44typedef double double4 __attribute__((ext_vector_type(4)));
45typedef char char2 __attribute__((ext_vector_type(2)));
46typedef char char3 __attribute__((ext_vector_type(3)));
47typedef char char4 __attribute__((ext_vector_type(4)));
48typedef unsigned char uchar2 __attribute__((ext_vector_type(2)));
49typedef unsigned char uchar3 __attribute__((ext_vector_type(3)));
50typedef unsigned char uchar4 __attribute__((ext_vector_type(4)));
51typedef int16_t short2 __attribute__((ext_vector_type(2)));
52typedef int16_t short3 __attribute__((ext_vector_type(3)));
53typedef int16_t short4 __attribute__((ext_vector_type(4)));
54typedef uint16_t ushort2 __attribute__((ext_vector_type(2)));
55typedef uint16_t ushort3 __attribute__((ext_vector_type(3)));
56typedef uint16_t ushort4 __attribute__((ext_vector_type(4)));
57typedef int32_t int2 __attribute__((ext_vector_type(2)));
58typedef int32_t int3 __attribute__((ext_vector_type(3)));
59typedef int32_t int4 __attribute__((ext_vector_type(4)));
60typedef uint32_t uint2 __attribute__((ext_vector_type(2)));
61typedef uint32_t uint3 __attribute__((ext_vector_type(3)));
62typedef uint32_t uint4 __attribute__((ext_vector_type(4)));
63typedef int64_t long2 __attribute__((ext_vector_type(2)));
64typedef int64_t long3 __attribute__((ext_vector_type(3)));
65typedef int64_t long4 __attribute__((ext_vector_type(4)));
66typedef uint64_t ulong2 __attribute__((ext_vector_type(2)));
67typedef uint64_t ulong3 __attribute__((ext_vector_type(3)));
68typedef uint64_t ulong4 __attribute__((ext_vector_type(4)));
69
70typedef uint8_t uchar;
71typedef uint16_t ushort;
72typedef uint32_t uint;
73typedef uint64_t ulong;
74
75// Add NOLINT to suppress wrong warnings from clang-tidy.
76#ifndef __LP64__
77#define OPAQUETYPE(t)   \
78  typedef struct {      \
79    const int *const p; \
80  } __attribute__((packed, aligned(4))) t; /*NOLINT*/
81#else
82#define OPAQUETYPE(t)     \
83  typedef struct {        \
84    const void *p;        \
85    const void *unused1;  \
86    const void *unused2;  \
87    const void *unused3;  \
88  } t; /*NOLINT*/
89#endif
90
91OPAQUETYPE(rs_element)
92OPAQUETYPE(rs_type)
93OPAQUETYPE(rs_allocation)
94OPAQUETYPE(rs_sampler)
95OPAQUETYPE(rs_script)
96OPAQUETYPE(rs_script_call)
97
98OPAQUETYPE(rs_program_fragment);
99OPAQUETYPE(rs_program_store);
100OPAQUETYPE(rs_program_vertex);
101OPAQUETYPE(rs_program_raster);
102OPAQUETYPE(rs_mesh);
103OPAQUETYPE(rs_font);
104
105#undef OPAQUETYPE
106
107typedef enum {
108  // Empty to avoid conflicting definitions with RsAllocationCubemapFace
109} rs_allocation_cubemap_face;
110
111typedef enum {
112  // Empty to avoid conflicting definitions with RsYuvFormat
113} rs_yuv_format;
114
115typedef enum {
116  // Empty to avoid conflicting definitions with RsAllocationMipmapControl
117} rs_allocation_mipmap_control;
118
119typedef struct { unsigned int val; } rs_allocation_usage_type;
120
121typedef struct {
122  int tm_sec;    ///< seconds
123  int tm_min;    ///< minutes
124  int tm_hour;   ///< hours
125  int tm_mday;   ///< day of the month
126  int tm_mon;    ///< month
127  int tm_year;   ///< year
128  int tm_wday;   ///< day of the week
129  int tm_yday;   ///< day of the year
130  int tm_isdst;  ///< daylight savings time
131} rs_tm;
132
133// Some RS functions are not threadsafe but can be called from an invoke
134// function.  Instead of summarily marking scripts that call these functions as
135// not-threadable we detect calls to them in the driver and sends a fatal error
136// message.
137static bool failIfInKernel(Context *rsc, const char *funcName) {
138  RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
139  RsdCpuReference *impl = (RsdCpuReference *)dc->mCpuRef;
140
141  if (impl->getInKernel()) {
142    char buf[256];
143    snprintf(buf, sizeof(buf),
144             "Error: Call to unsupported function %s "
145             "in kernel",
146             funcName);
147    rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
148    return true;
149  }
150  return false;
151}
152
153//////////////////////////////////////////////////////////////////////////////
154// Allocation routines
155//////////////////////////////////////////////////////////////////////////////
156#if defined(__i386__) || (defined(__mips__) && __mips == 32)
157// i386 and MIPS32 have different struct return passing to ARM; emulate with a
158// pointer
159const Allocation *rsGetAllocation(const void *ptr) {
160  Context *rsc = RsdCpuReference::getTlsContext();
161  const Script *sc = RsdCpuReference::getTlsScript();
162  Allocation *alloc = rsovScriptGetAllocationForPointer(rsc, sc, ptr);
163  android::renderscript::rs_allocation obj = {0};
164  alloc->callUpdateCacheObject(rsc, &obj);
165  return (Allocation *)obj.p;
166}
167#else
168const android::renderscript::rs_allocation rsGetAllocation(const void *ptr) {
169  Context *rsc = RsdCpuReference::getTlsContext();
170  const Script *sc = RsdCpuReference::getTlsScript();
171  Allocation *alloc = rsovScriptGetAllocationForPointer(rsc, sc, ptr);
172
173#ifndef __LP64__  // ARMv7
174  android::renderscript::rs_allocation obj = {0};
175#else             // AArch64/x86_64/MIPS64
176  android::renderscript::rs_allocation obj = {0, 0, 0, 0};
177#endif
178  alloc->callUpdateCacheObject(rsc, &obj);
179  return obj;
180}
181#endif
182
183void __attribute__((overloadable)) rsAllocationIoSend(::rs_allocation a) {
184  Context *rsc = RsdCpuReference::getTlsContext();
185  if (failIfInKernel(rsc, "rsAllocationIoSend")) return;
186  rsrAllocationIoSend(rsc, (Allocation *)a.p);
187}
188
189void __attribute__((overloadable)) rsAllocationIoReceive(::rs_allocation a) {
190  Context *rsc = RsdCpuReference::getTlsContext();
191  if (failIfInKernel(rsc, "rsAllocationIoReceive")) return;
192  rsrAllocationIoReceive(rsc, (Allocation *)a.p);
193}
194
195void __attribute__((overloadable))
196rsAllocationCopy1DRange(::rs_allocation dstAlloc, uint32_t dstOff,
197                        uint32_t dstMip, uint32_t count,
198                        ::rs_allocation srcAlloc, uint32_t srcOff,
199                        uint32_t srcMip) {
200  Context *rsc = RsdCpuReference::getTlsContext();
201  if (failIfInKernel(rsc, "rsAllocationCopy1DRange")) return;
202  rsrAllocationCopy1DRange(rsc, (Allocation *)dstAlloc.p, dstOff, dstMip, count,
203                           (Allocation *)srcAlloc.p, srcOff, srcMip);
204}
205
206void __attribute__((overloadable))
207rsAllocationCopy2DRange(::rs_allocation dstAlloc, uint32_t dstXoff,
208                        uint32_t dstYoff, uint32_t dstMip,
209                        rs_allocation_cubemap_face dstFace, uint32_t width,
210                        uint32_t height, ::rs_allocation srcAlloc,
211                        uint32_t srcXoff, uint32_t srcYoff, uint32_t srcMip,
212                        rs_allocation_cubemap_face srcFace) {
213  Context *rsc = RsdCpuReference::getTlsContext();
214  if (failIfInKernel(rsc, "rsAllocationCopy2DRange")) return;
215  rsrAllocationCopy2DRange(
216      rsc, (Allocation *)dstAlloc.p, dstXoff, dstYoff, dstMip, dstFace, width,
217      height, (Allocation *)srcAlloc.p, srcXoff, srcYoff, srcMip, srcFace);
218}
219
220static android::renderscript::rs_element CreateElement(RsDataType dt,
221                                                       RsDataKind dk,
222                                                       bool isNormalized,
223                                                       uint32_t vecSize) {
224  Context *rsc = RsdCpuReference::getTlsContext();
225
226  // No need for validation here.  The rsCreateElement overload below is not
227  // exposed to the Script.  The Element-creation APIs call this function in a
228  // consistent manner and rsComponent.cpp asserts on any inconsistency.
229  Element *element =
230      (Element *)rsrElementCreate(rsc, dt, dk, isNormalized, vecSize);
231  android::renderscript::rs_element obj = {};
232  if (element == nullptr) return obj;
233  element->callUpdateCacheObject(rsc, &obj);
234
235  // Any new rsObject created from inside a script should have the usrRefCount
236  // initialized to 0 and the sysRefCount initialized to 1.
237  element->incSysRef();
238  element->decUserRef();
239
240  return obj;
241}
242
243static android::renderscript::rs_type CreateType(RsElement element,
244                                                 uint32_t dimX, uint32_t dimY,
245                                                 uint32_t dimZ, bool mipmaps,
246                                                 bool faces,
247                                                 uint32_t yuv_format) {
248  Context *rsc = RsdCpuReference::getTlsContext();
249  android::renderscript::rs_type obj = {};
250
251  if (element == nullptr) {
252    ALOGE("rs_type creation error: Invalid element");
253    return obj;
254  }
255
256  // validate yuv_format
257  RsYuvFormat yuv = (RsYuvFormat)yuv_format;
258  if (yuv != RS_YUV_NONE && yuv != RS_YUV_YV12 && yuv != RS_YUV_NV21 &&
259      yuv != RS_YUV_420_888) {
260    ALOGE("rs_type creation error: Invalid yuv_format %d\n", yuv_format);
261    return obj;
262  }
263
264  // validate consistency of shape parameters
265  if (dimZ > 0) {
266    if (dimX < 1 || dimY < 1) {
267      ALOGE(
268          "rs_type creation error: Both X and Y dimension required "
269          "when Z is present.");
270      return obj;
271    }
272    if (mipmaps) {
273      ALOGE("rs_type creation error: mipmap control requires 2D types");
274      return obj;
275    }
276    if (faces) {
277      ALOGE("rs_type creation error: Cube maps require 2D types");
278      return obj;
279    }
280  }
281  if (dimY > 0 && dimX < 1) {
282    ALOGE(
283        "rs_type creation error: X dimension required when Y is "
284        "present.");
285    return obj;
286  }
287  if (mipmaps && dimY < 1) {
288    ALOGE("rs_type creation error: mipmap control require 2D Types.");
289    return obj;
290  }
291  if (faces && dimY < 1) {
292    ALOGE("rs_type creation error: Cube maps require 2D Types.");
293    return obj;
294  }
295  if (yuv_format != RS_YUV_NONE) {
296    if (dimZ != 0 || dimY == 0 || faces || mipmaps) {
297      ALOGE("rs_type creation error: YUV only supports basic 2D.");
298      return obj;
299    }
300  }
301
302  Type *type = (Type *)rsrTypeCreate(rsc, element, dimX, dimY, dimZ, mipmaps,
303                                     faces, yuv_format);
304  if (type == nullptr) return obj;
305  type->callUpdateCacheObject(rsc, &obj);
306
307  // Any new rsObject created from inside a script should have the usrRefCount
308  // initialized to 0 and the sysRefCount initialized to 1.
309  type->incSysRef();
310  type->decUserRef();
311
312  return obj;
313}
314
315static android::renderscript::rs_allocation CreateAllocation(
316    RsType type, RsAllocationMipmapControl mipmaps, uint32_t usages,
317    void *ptr) {
318  Context *rsc = RsdCpuReference::getTlsContext();
319  android::renderscript::rs_allocation obj = {};
320
321  if (type == nullptr) {
322    ALOGE("rs_allocation creation error: Invalid type");
323    return obj;
324  }
325
326  uint32_t validUsages =
327      RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
328  if (usages & ~validUsages) {
329    ALOGE("rs_allocation creation error: Invalid usage flag");
330    return obj;
331  }
332
333  Allocation *alloc = (Allocation *)rsrAllocationCreateTyped(
334      rsc, type, mipmaps, usages, (uintptr_t)ptr);
335  if (alloc == nullptr) return obj;
336  alloc->callUpdateCacheObject(rsc, &obj);
337
338  // Any new rsObject created from inside a script should have the usrRefCount
339  // initialized to 0 and the sysRefCount initialized to 1.
340  alloc->incSysRef();
341  alloc->decUserRef();
342
343  return obj;
344}
345
346// Define rsCreateElement, rsCreateType and rsCreateAllocation entry points
347// differently for 32-bit x86 and Mips.  The definitions for ARM32 and all
348// 64-bit architectures is further below.
349#if defined(__i386__) || (defined(__mips__) && __mips == 32)
350
351// The calling convention for the driver on 32-bit x86 and Mips returns
352// rs_element etc. as a stack-return parameter.  The Script uses ARM32 calling
353// conventions that return the structs in a register.  To match this convention,
354// emulate the return value using a pointer.
355Element *rsCreateElement(int32_t dt, int32_t dk, bool isNormalized,
356                         uint32_t vecSize) {
357  android::renderscript::rs_element obj =
358      CreateElement((RsDataType)dt, (RsDataKind)dk, isNormalized, vecSize);
359  return (Element *)obj.p;
360}
361
362Type *rsCreateType(::rs_element element, uint32_t dimX, uint32_t dimY,
363                   uint32_t dimZ, bool mipmaps, bool faces,
364                   rs_yuv_format yuv_format) {
365  android::renderscript::rs_type obj =
366      CreateType((RsElement)element.p, dimX, dimY, dimZ, mipmaps, faces,
367                 (RsYuvFormat)yuv_format);
368  return (Type *)obj.p;
369}
370
371Allocation *rsCreateAllocation(::rs_type type,
372                               rs_allocation_mipmap_control mipmaps,
373                               uint32_t usages, void *ptr) {
374  android::renderscript::rs_allocation obj;
375  obj = CreateAllocation((RsType)type.p, (RsAllocationMipmapControl)mipmaps,
376                         usages, ptr);
377  return (Allocation *)obj.p;
378}
379
380#else
381android::renderscript::rs_element rsCreateElement(int32_t dt, int32_t dk,
382                                                  bool isNormalized,
383                                                  uint32_t vecSize) {
384  return CreateElement((RsDataType)dt, (RsDataKind)dk, isNormalized, vecSize);
385}
386
387android::renderscript::rs_type rsCreateType(::rs_element element, uint32_t dimX,
388                                            uint32_t dimY, uint32_t dimZ,
389                                            bool mipmaps, bool faces,
390                                            rs_yuv_format yuv_format) {
391  return CreateType((RsElement)element.p, dimX, dimY, dimZ, mipmaps, faces,
392                    yuv_format);
393}
394
395android::renderscript::rs_allocation rsCreateAllocation(
396    ::rs_type type, rs_allocation_mipmap_control mipmaps, uint32_t usages,
397    void *ptr) {
398  return CreateAllocation((RsType)type.p, (RsAllocationMipmapControl)mipmaps,
399                          usages, ptr);
400}
401#endif
402
403//////////////////////////////////////////////////////////////////////////////
404// Object routines
405//////////////////////////////////////////////////////////////////////////////
406// Add NOLINT to suppress wrong warnings from clang-tidy.
407#define IS_CLEAR_SET_OBJ(t)                                                  \
408  bool rsIsObject(t src) { return src.p != nullptr; }                        \
409  void __attribute__((overloadable)) rsClearObject(t *dst) { /*NOLINT*/      \
410    rsrClearObject(reinterpret_cast<rs_object_base *>(dst));                 \
411  }                                                                          \
412  void __attribute__((overloadable)) rsSetObject(t *dst, t src) { /*NOLINT*/ \
413    Context *rsc = RsdCpuReference::getTlsContext();                         \
414    rsrSetObject(rsc, reinterpret_cast<rs_object_base *>(dst),               \
415                 (ObjectBase *)src.p);                                       \
416  }
417
418IS_CLEAR_SET_OBJ(::rs_element)
419IS_CLEAR_SET_OBJ(::rs_type)
420IS_CLEAR_SET_OBJ(::rs_allocation)
421IS_CLEAR_SET_OBJ(::rs_sampler)
422IS_CLEAR_SET_OBJ(::rs_script)
423
424IS_CLEAR_SET_OBJ(::rs_mesh)
425IS_CLEAR_SET_OBJ(::rs_program_fragment)
426IS_CLEAR_SET_OBJ(::rs_program_vertex)
427IS_CLEAR_SET_OBJ(::rs_program_raster)
428IS_CLEAR_SET_OBJ(::rs_program_store)
429IS_CLEAR_SET_OBJ(::rs_font)
430
431#undef IS_CLEAR_SET_OBJ
432
433//////////////////////////////////////////////////////////////////////////////
434// Element routines
435//////////////////////////////////////////////////////////////////////////////
436static void *ElementAt(Allocation *a, RsDataType dt, uint32_t vecSize,
437                       uint32_t x, uint32_t y, uint32_t z) {
438  Context *rsc = RsdCpuReference::getTlsContext();
439  const Type *t = a->getType();
440  const Element *e = t->getElement();
441
442  char buf[256];
443  if (x && (x >= t->getLODDimX(0))) {
444    snprintf(buf, sizeof(buf), "Out range ElementAt X %i of %i", x,
445             t->getLODDimX(0));
446    rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
447    return nullptr;
448  }
449
450  if (y && (y >= t->getLODDimY(0))) {
451    snprintf(buf, sizeof(buf), "Out range ElementAt Y %i of %i", y,
452             t->getLODDimY(0));
453    rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
454    return nullptr;
455  }
456
457  if (z && (z >= t->getLODDimZ(0))) {
458    snprintf(buf, sizeof(buf), "Out range ElementAt Z %i of %i", z,
459             t->getLODDimZ(0));
460    rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
461    return nullptr;
462  }
463
464  if (vecSize > 0) {
465    if (vecSize != e->getVectorSize()) {
466      snprintf(buf, sizeof(buf), "Vector size mismatch for ElementAt %i of %i",
467               vecSize, e->getVectorSize());
468      rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
469      return nullptr;
470    }
471
472    if (dt != e->getType()) {
473      snprintf(buf, sizeof(buf), "Data type mismatch for ElementAt %i of %i",
474               dt, e->getType());
475      rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
476      return nullptr;
477    }
478  }
479
480  uint8_t *p = (uint8_t *)a->mHal.drvState.lod[0].mallocPtr;
481  const uint32_t eSize = e->getSizeBytes();
482  const uint32_t stride = a->mHal.drvState.lod[0].stride;
483  const uint32_t dimY = a->mHal.drvState.lod[0].dimY;
484  return &p[(x * eSize) + (y * stride) + (z * stride * dimY)];
485}
486
487void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x, uint32_t y,
488                    uint32_t z) {
489  const Type *t = const_cast<Allocation *>((Allocation *)a.p)->getType();
490  const Element *e = t->getElement();
491  void *tmp = ElementAt((Allocation *)a.p, RS_TYPE_UNSIGNED_8, 0, x, y, z);
492  if (tmp != nullptr) memcpy(tmp, ptr, e->getSizeBytes());
493}
494
495void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x,
496                    uint32_t y) {
497  rsSetElementAt(a, ptr, x, y, 0);
498}
499
500void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x) {
501  rsSetElementAt(a, ptr, x, 0, 0);
502}
503
504const void *rsGetElementAt(::rs_allocation a, uint32_t x, uint32_t y,
505                           uint32_t z) {
506  return ElementAt((Allocation *)a.p, RS_TYPE_UNSIGNED_8, 0, x, y, z);
507}
508
509const void *rsGetElementAt(::rs_allocation a, uint32_t x, uint32_t y) {
510  return rsGetElementAt(a, x, y, 0);
511}
512
513const void *rsGetElementAt(::rs_allocation a, uint32_t x) {
514  return rsGetElementAt(a, x, 0, 0);
515}
516
517// Add NOLINT to suppress wrong warnings from clang-tidy.
518#define ELEMENT_AT(T, DT, VS)                                                 \
519  void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x,        \
520                          uint32_t y, uint32_t z) {                           \
521    void *r = ElementAt((Allocation *)a.p, DT, VS, x, y, z);                  \
522    if (r != nullptr)                                                         \
523      ((T *)r)[0] = *val;                                                     \
524    else                                                                      \
525      ALOGE("Error from %s", __PRETTY_FUNCTION__);                            \
526  }                                                                           \
527  void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x,        \
528                          uint32_t y) {                                       \
529    rsSetElementAt_##T(a, val, x, y, 0);                                      \
530  }                                                                           \
531  void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x) {      \
532    rsSetElementAt_##T(a, val, x, 0, 0);                                      \
533  }                                                                           \
534  void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x, uint32_t y,  \
535                          uint32_t z) { /*NOLINT*/                            \
536    void *r = ElementAt((Allocation *)a.p, DT, VS, x, y, z);                  \
537    if (r != nullptr)                                                         \
538      *val = ((T *)r)[0];                                                     \
539    else                                                                      \
540      ALOGE("Error from %s", __PRETTY_FUNCTION__);                            \
541  }                                                                           \
542  void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x,              \
543                          uint32_t y) { /*NOLINT*/                            \
544    rsGetElementAt_##T(a, val, x, y, 0);                                      \
545  }                                                                           \
546  void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x) { /*NOLINT*/ \
547    rsGetElementAt_##T(a, val, x, 0, 0);                                      \
548  }
549
550ELEMENT_AT(char, RS_TYPE_SIGNED_8, 1)
551ELEMENT_AT(char2, RS_TYPE_SIGNED_8, 2)
552ELEMENT_AT(char3, RS_TYPE_SIGNED_8, 3)
553ELEMENT_AT(char4, RS_TYPE_SIGNED_8, 4)
554ELEMENT_AT(uchar, RS_TYPE_UNSIGNED_8, 1)
555ELEMENT_AT(uchar2, RS_TYPE_UNSIGNED_8, 2)
556ELEMENT_AT(uchar3, RS_TYPE_UNSIGNED_8, 3)
557ELEMENT_AT(uchar4, RS_TYPE_UNSIGNED_8, 4)
558ELEMENT_AT(short, RS_TYPE_SIGNED_16, 1)
559ELEMENT_AT(short2, RS_TYPE_SIGNED_16, 2)
560ELEMENT_AT(short3, RS_TYPE_SIGNED_16, 3)
561ELEMENT_AT(short4, RS_TYPE_SIGNED_16, 4)
562ELEMENT_AT(ushort, RS_TYPE_UNSIGNED_16, 1)
563ELEMENT_AT(ushort2, RS_TYPE_UNSIGNED_16, 2)
564ELEMENT_AT(ushort3, RS_TYPE_UNSIGNED_16, 3)
565ELEMENT_AT(ushort4, RS_TYPE_UNSIGNED_16, 4)
566ELEMENT_AT(int, RS_TYPE_SIGNED_32, 1)
567ELEMENT_AT(int2, RS_TYPE_SIGNED_32, 2)
568ELEMENT_AT(int3, RS_TYPE_SIGNED_32, 3)
569ELEMENT_AT(int4, RS_TYPE_SIGNED_32, 4)
570ELEMENT_AT(uint, RS_TYPE_UNSIGNED_32, 1)
571ELEMENT_AT(uint2, RS_TYPE_UNSIGNED_32, 2)
572ELEMENT_AT(uint3, RS_TYPE_UNSIGNED_32, 3)
573ELEMENT_AT(uint4, RS_TYPE_UNSIGNED_32, 4)
574ELEMENT_AT(long, RS_TYPE_SIGNED_64, 1)
575ELEMENT_AT(long2, RS_TYPE_SIGNED_64, 2)
576ELEMENT_AT(long3, RS_TYPE_SIGNED_64, 3)
577ELEMENT_AT(long4, RS_TYPE_SIGNED_64, 4)
578ELEMENT_AT(ulong, RS_TYPE_UNSIGNED_64, 1)
579ELEMENT_AT(ulong2, RS_TYPE_UNSIGNED_64, 2)
580ELEMENT_AT(ulong3, RS_TYPE_UNSIGNED_64, 3)
581ELEMENT_AT(ulong4, RS_TYPE_UNSIGNED_64, 4)
582ELEMENT_AT(half, RS_TYPE_FLOAT_16, 1)
583ELEMENT_AT(half2, RS_TYPE_FLOAT_16, 2)
584ELEMENT_AT(half3, RS_TYPE_FLOAT_16, 3)
585ELEMENT_AT(half4, RS_TYPE_FLOAT_16, 4)
586ELEMENT_AT(float, RS_TYPE_FLOAT_32, 1)
587ELEMENT_AT(float2, RS_TYPE_FLOAT_32, 2)
588ELEMENT_AT(float3, RS_TYPE_FLOAT_32, 3)
589ELEMENT_AT(float4, RS_TYPE_FLOAT_32, 4)
590ELEMENT_AT(double, RS_TYPE_FLOAT_64, 1)
591ELEMENT_AT(double2, RS_TYPE_FLOAT_64, 2)
592ELEMENT_AT(double3, RS_TYPE_FLOAT_64, 3)
593ELEMENT_AT(double4, RS_TYPE_FLOAT_64, 4)
594
595#undef ELEMENT_AT
596
597#ifndef __LP64__
598/*
599 * We miss some symbols for rs{Get,Set}Element_long,ulong variants because 64
600 * bit integer values are 'long' in RS-land but might be 'long long' in the
601 * driver.  Define native_long* and native_ulong* types to be vectors of
602 * 'long' as seen by the driver and define overloaded versions of
603 * rsSetElementAt_* and rsGetElementAt_*.  This should get us the correct
604 * mangled names in the driver.
605 */
606
607typedef long native_long2 __attribute__((ext_vector_type(2)));
608typedef long native_long3 __attribute__((ext_vector_type(3)));
609typedef long native_long4 __attribute__((ext_vector_type(4)));
610typedef unsigned long native_ulong2 __attribute__((ext_vector_type(2)));
611typedef unsigned long native_ulong3 __attribute__((ext_vector_type(3)));
612typedef unsigned long native_ulong4 __attribute__((ext_vector_type(4)));
613
614// Add NOLINT to suppress wrong warnings from clang-tidy.
615#define ELEMENT_AT_OVERLOADS(T, U)                                            \
616  void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x,        \
617                          uint32_t y, uint32_t z) {                           \
618    rsSetElementAt_##T(a, (T *)val, x, y, z);                                 \
619  }                                                                           \
620  void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x,        \
621                          uint32_t y) {                                       \
622    rsSetElementAt_##T(a, (T *)val, x, y, 0);                                 \
623  }                                                                           \
624  void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x) {      \
625    rsSetElementAt_##T(a, (T *)val, x, 0, 0);                                 \
626  }                                                                           \
627  void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x, uint32_t y,  \
628                          uint32_t z) { /*NOLINT*/                            \
629    rsGetElementAt_##T(a, (T *)val, x, y, z);                                 \
630  }                                                                           \
631  void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x,              \
632                          uint32_t y) { /*NOLINT*/                            \
633    rsGetElementAt_##T(a, (T *)val, x, y, 0);                                 \
634  }                                                                           \
635  void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x) { /*NOLINT*/ \
636    rsGetElementAt_##T(a, (T *)val, x, 0, 0);                                 \
637  }
638
639ELEMENT_AT_OVERLOADS(long2, native_long2)
640ELEMENT_AT_OVERLOADS(long3, native_long3)
641ELEMENT_AT_OVERLOADS(long4, native_long4)
642ELEMENT_AT_OVERLOADS(ulong, unsigned long)
643ELEMENT_AT_OVERLOADS(ulong2, native_ulong2)
644ELEMENT_AT_OVERLOADS(ulong3, native_ulong3)
645ELEMENT_AT_OVERLOADS(ulong4, native_ulong4)
646
647// We also need variants of rs{Get,Set}ElementAt_long that take 'long long *' as
648// we might have this overloaded variant in old APKs.
649ELEMENT_AT_OVERLOADS(long, long long)
650
651#undef ELEMENT_AT_OVERLOADS
652#endif
653
654//////////////////////////////////////////////////////////////////////////////
655// ForEach routines
656//////////////////////////////////////////////////////////////////////////////
657void rsForEachInternal(int slot, rs_script_call *options, int hasOutput,
658                       int numInputs, ::rs_allocation *allocs) {
659  Context *rsc = RsdCpuReference::getTlsContext();
660  Script *s = const_cast<Script *>(RsdCpuReference::getTlsScript());
661  if (numInputs > RS_KERNEL_MAX_ARGUMENTS) {
662    rsc->setError(RS_ERROR_BAD_SCRIPT,
663                  "rsForEachInternal: too many inputs to a kernel.");
664    return;
665  }
666  Allocation *inputs[RS_KERNEL_MAX_ARGUMENTS];
667  for (int i = 0; i < numInputs; i++) {
668    inputs[i] = (Allocation *)allocs[i].p;
669  }
670  Allocation *out = hasOutput ? (Allocation *)allocs[numInputs].p : nullptr;
671  rsrForEach(rsc, s, slot, numInputs, numInputs > 0 ? inputs : nullptr, out,
672             nullptr, 0, (RsScriptCall *)options);
673}
674
675void __attribute__((overloadable))
676rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
677          const void *usr, const rs_script_call *call) {
678  Context *rsc = RsdCpuReference::getTlsContext();
679  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
680             (Allocation *)out.p, usr, 0, (RsScriptCall *)call);
681}
682
683void __attribute__((overloadable))
684rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
685          const void *usr) {
686  Context *rsc = RsdCpuReference::getTlsContext();
687  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
688             (Allocation *)out.p, usr, 0, nullptr);
689}
690
691void __attribute__((overloadable))
692rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out) {
693  Context *rsc = RsdCpuReference::getTlsContext();
694  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
695             (Allocation *)out.p, nullptr, 0, nullptr);
696}
697
698// These functions are only supported in 32-bit.
699#ifndef __LP64__
700void __attribute__((overloadable))
701rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
702          const void *usr, uint32_t usrLen) {
703  Context *rsc = RsdCpuReference::getTlsContext();
704  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
705             (Allocation *)out.p, usr, usrLen, nullptr);
706}
707
708void __attribute__((overloadable))
709rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
710          const void *usr, uint32_t usrLen, const rs_script_call *call) {
711  Context *rsc = RsdCpuReference::getTlsContext();
712  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
713             (Allocation *)out.p, usr, usrLen, (RsScriptCall *)call);
714}
715#endif
716
717//////////////////////////////////////////////////////////////////////////////
718// Message routines
719//////////////////////////////////////////////////////////////////////////////
720uint32_t rsSendToClient(int cmdID) {
721  Context *rsc = RsdCpuReference::getTlsContext();
722  return rsrToClient(rsc, cmdID, (const void *)nullptr, 0);
723}
724
725uint32_t rsSendToClient(int cmdID, const void *data, uint32_t len) {
726  Context *rsc = RsdCpuReference::getTlsContext();
727  return rsrToClient(rsc, cmdID, data, len);
728}
729
730uint32_t rsSendToClientBlocking(int cmdID) {
731  Context *rsc = RsdCpuReference::getTlsContext();
732  return rsrToClientBlocking(rsc, cmdID, (const void *)nullptr, 0);
733}
734
735uint32_t rsSendToClientBlocking(int cmdID, const void *data, uint32_t len) {
736  Context *rsc = RsdCpuReference::getTlsContext();
737  return rsrToClientBlocking(rsc, cmdID, data, len);
738}
739
740//////////////////////////////////////////////////////////////////////////////
741// Time routines
742//////////////////////////////////////////////////////////////////////////////
743
744// time_t is int in 32-bit RenderScript.  time_t is long in bionic.  rsTime and
745// rsLocaltime are set to explicitly take 'const int *' so we generate the
746// correct mangled names.
747#ifndef __LP64__
748int rsTime(int *timer) {
749#else
750time_t rsTime(time_t *timer) {
751#endif
752  Context *rsc = RsdCpuReference::getTlsContext();
753  return rsrTime(rsc, (time_t *)timer);
754}
755
756#ifndef __LP64__
757rs_tm *rsLocaltime(rs_tm *local, const int *timer) {
758#else
759rs_tm *rsLocaltime(rs_tm *local, const time_t *timer) {
760#endif
761  Context *rsc = RsdCpuReference::getTlsContext();
762  return (rs_tm *)rsrLocalTime(rsc, (tm *)local, (time_t *)timer);
763}
764
765int64_t rsUptimeMillis() {
766  Context *rsc = RsdCpuReference::getTlsContext();
767  return rsrUptimeMillis(rsc);
768}
769
770int64_t rsUptimeNanos() {
771  Context *rsc = RsdCpuReference::getTlsContext();
772  return rsrUptimeNanos(rsc);
773}
774
775float rsGetDt() {
776  Context *rsc = RsdCpuReference::getTlsContext();
777  const Script *sc = RsdCpuReference::getTlsScript();
778  return rsrGetDt(rsc, sc);
779}
780
781//////////////////////////////////////////////////////////////////////////////
782// Debug routines
783//////////////////////////////////////////////////////////////////////////////
784void rsDebug(const char *s, float f) {
785  ALOGD("%s %f, 0x%08x", s, f, *((int *)(&f)));
786}
787
788void rsDebug(const char *s, float f1, float f2) {
789  ALOGD("%s {%f, %f}", s, f1, f2);
790}
791
792void rsDebug(const char *s, float f1, float f2, float f3) {
793  ALOGD("%s {%f, %f, %f}", s, f1, f2, f3);
794}
795
796void rsDebug(const char *s, float f1, float f2, float f3, float f4) {
797  ALOGD("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4);
798}
799
800void rsDebug(const char *s, const float2 *f2) {
801  float2 f = *f2;
802  ALOGD("%s {%f, %f}", s, f.x, f.y);
803}
804
805void rsDebug(const char *s, const float3 *f3) {
806  float3 f = *f3;
807  ALOGD("%s {%f, %f, %f}", s, f.x, f.y, f.z);
808}
809
810void rsDebug(const char *s, const float4 *f4) {
811  float4 f = *f4;
812  ALOGD("%s {%f, %f, %f, %f}", s, f.x, f.y, f.z, f.w);
813}
814
815// Accept a half value converted to float.  This eliminates the need in the
816// driver to properly support the half datatype (either by adding compiler flags
817// for half or link against compiler_rt).
818void rsDebug(const char *s, float f, ushort us) {
819  ALOGD("%s {%f} {0x%hx}", s, f, us);
820}
821
822void rsDebug(const char *s, const float2 *f2, const ushort2 *us2) {
823  float2 f = *f2;
824  ushort2 us = *us2;
825  ALOGD("%s {%f %f} {0x%hx 0x%hx}", s, f.x, f.y, us.x, us.y);
826}
827
828void rsDebug(const char *s, const float3 *f3, const ushort3 *us3) {
829  float3 f = *f3;
830  ushort3 us = *us3;
831  ALOGD("%s {%f %f %f} {0x%hx 0x%hx 0x%hx}", s, f.x, f.y, f.z, us.x, us.y,
832        us.z);
833}
834
835void rsDebug(const char *s, const float4 *f4, const ushort4 *us4) {
836  float4 f = *f4;
837  ushort4 us = *us4;
838  ALOGD("%s {%f %f %f %f} {0x%hx 0x%hx 0x%hx 0x%hx}", s, f.x, f.y, f.z, f.w,
839        us.x, us.y, us.z, us.w);
840}
841
842void rsDebug(const char *s, double d) {
843  ALOGD("%s %f, 0x%08llx", s, d, *((long long *)(&d)));
844}
845
846void rsDebug(const char *s, const double2 *d2) {
847  double2 d = *d2;
848  ALOGD("%s {%f, %f}", s, d.x, d.y);
849}
850
851void rsDebug(const char *s, const double3 *d3) {
852  double3 d = *d3;
853  ALOGD("%s {%f, %f, %f}", s, d.x, d.y, d.z);
854}
855
856void rsDebug(const char *s, const double4 *d4) {
857  double4 d = *d4;
858  ALOGD("%s {%f, %f, %f, %f}", s, d.x, d.y, d.z, d.w);
859}
860
861void rsDebug(const char *s, const rs_matrix4x4 *m) {
862  float *f = (float *)m;
863  ALOGD("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]);
864  ALOGD("%s  %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]);
865  ALOGD("%s  %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]);
866  ALOGD("%s  %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]);
867}
868
869void rsDebug(const char *s, const rs_matrix3x3 *m) {
870  float *f = (float *)m;
871  ALOGD("%s {%f, %f, %f", s, f[0], f[3], f[6]);
872  ALOGD("%s  %f, %f, %f", s, f[1], f[4], f[7]);
873  ALOGD("%s  %f, %f, %f}", s, f[2], f[5], f[8]);
874}
875
876void rsDebug(const char *s, const rs_matrix2x2 *m) {
877  float *f = (float *)m;
878  ALOGD("%s {%f, %f", s, f[0], f[2]);
879  ALOGD("%s  %f, %f}", s, f[1], f[3]);
880}
881
882void rsDebug(const char *s, char c) {
883  ALOGD("%s %hhd  0x%hhx", s, c, (unsigned char)c);
884}
885
886void rsDebug(const char *s, const char2 *c2) {
887  char2 c = *c2;
888  ALOGD("%s {%hhd, %hhd}  0x%hhx 0x%hhx", s, c.x, c.y, (unsigned char)c.x,
889        (unsigned char)c.y);
890}
891
892void rsDebug(const char *s, const char3 *c3) {
893  char3 c = *c3;
894  ALOGD("%s {%hhd, %hhd, %hhd}  0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y, c.z,
895        (unsigned char)c.x, (unsigned char)c.y, (unsigned char)c.z);
896}
897
898void rsDebug(const char *s, const char4 *c4) {
899  char4 c = *c4;
900  ALOGD("%s {%hhd, %hhd, %hhd, %hhd}  0x%hhx 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y,
901        c.z, c.w, (unsigned char)c.x, (unsigned char)c.y, (unsigned char)c.z,
902        (unsigned char)c.w);
903}
904
905void rsDebug(const char *s, unsigned char c) {
906  ALOGD("%s %hhu  0x%hhx", s, c, c);
907}
908
909void rsDebug(const char *s, const uchar2 *c2) {
910  uchar2 c = *c2;
911  ALOGD("%s {%hhu, %hhu}  0x%hhx 0x%hhx", s, c.x, c.y, c.x, c.y);
912}
913
914void rsDebug(const char *s, const uchar3 *c3) {
915  uchar3 c = *c3;
916  ALOGD("%s {%hhu, %hhu, %hhu}  0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y, c.z, c.x,
917        c.y, c.z);
918}
919
920void rsDebug(const char *s, const uchar4 *c4) {
921  uchar4 c = *c4;
922  ALOGD("%s {%hhu, %hhu, %hhu, %hhu}  0x%hhx 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y,
923        c.z, c.w, c.x, c.y, c.z, c.w);
924}
925
926void rsDebug(const char *s, short c) { ALOGD("%s %hd  0x%hx", s, c, c); }
927
928void rsDebug(const char *s, const short2 *c2) {
929  short2 c = *c2;
930  ALOGD("%s {%hd, %hd}  0x%hx 0x%hx", s, c.x, c.y, c.x, c.y);
931}
932
933void rsDebug(const char *s, const short3 *c3) {
934  short3 c = *c3;
935  ALOGD("%s {%hd, %hd, %hd}  0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z, c.x, c.y,
936        c.z);
937}
938
939void rsDebug(const char *s, const short4 *c4) {
940  short4 c = *c4;
941  ALOGD("%s {%hd, %hd, %hd, %hd}  0x%hx 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z,
942        c.w, c.x, c.y, c.z, c.w);
943}
944
945void rsDebug(const char *s, unsigned short c) {
946  ALOGD("%s %hu  0x%hx", s, c, c);
947}
948
949void rsDebug(const char *s, const ushort2 *c2) {
950  ushort2 c = *c2;
951  ALOGD("%s {%hu, %hu}  0x%hx 0x%hx", s, c.x, c.y, c.x, c.y);
952}
953
954void rsDebug(const char *s, const ushort3 *c3) {
955  ushort3 c = *c3;
956  ALOGD("%s {%hu, %hu, %hu}  0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z, c.x, c.y,
957        c.z);
958}
959
960void rsDebug(const char *s, const ushort4 *c4) {
961  ushort4 c = *c4;
962  ALOGD("%s {%hu, %hu, %hu, %hu}  0x%hx 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z,
963        c.w, c.x, c.y, c.z, c.w);
964}
965
966void rsDebug(const char *s, int i) { ALOGD("%s %d  0x%x", s, i, i); }
967
968void rsDebug(const char *s, const int2 *i2) {
969  int2 i = *i2;
970  ALOGD("%s {%d, %d}  0x%x 0x%x", s, i.x, i.y, i.x, i.y);
971}
972
973void rsDebug(const char *s, const int3 *i3) {
974  int3 i = *i3;
975  ALOGD("%s {%d, %d, %d}  0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.x, i.y, i.z);
976}
977
978void rsDebug(const char *s, const int4 *i4) {
979  int4 i = *i4;
980  ALOGD("%s {%d, %d, %d, %d}  0x%x 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.w, i.x,
981        i.y, i.z, i.w);
982}
983
984void rsDebug(const char *s, unsigned int i) { ALOGD("%s %u  0x%x", s, i, i); }
985
986void rsDebug(const char *s, const uint2 *i2) {
987  uint2 i = *i2;
988  ALOGD("%s {%u, %u}  0x%x 0x%x", s, i.x, i.y, i.x, i.y);
989}
990
991void rsDebug(const char *s, const uint3 *i3) {
992  uint3 i = *i3;
993  ALOGD("%s {%u, %u, %u}  0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.x, i.y, i.z);
994}
995
996void rsDebug(const char *s, const uint4 *i4) {
997  uint4 i = *i4;
998  ALOGD("%s {%u, %u, %u, %u}  0x%x 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.w, i.x,
999        i.y, i.z, i.w);
1000}
1001
1002template <typename T>
1003static inline long long LL(const T &x) {
1004  return static_cast<long long>(x);
1005}
1006
1007template <typename T>
1008static inline unsigned long long LLu(const T &x) {
1009  return static_cast<unsigned long long>(x);
1010}
1011
1012void rsDebug(const char *s, long l) {
1013  ALOGD("%s %lld  0x%llx", s, LL(l), LL(l));
1014}
1015
1016void rsDebug(const char *s, long long ll) {
1017  ALOGD("%s %lld  0x%llx", s, LL(ll), LL(ll));
1018}
1019
1020void rsDebug(const char *s, const long2 *c) {
1021  long2 ll = *c;
1022  ALOGD("%s {%lld, %lld}  0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
1023        LL(ll.y));
1024}
1025
1026void rsDebug(const char *s, const long3 *c) {
1027  long3 ll = *c;
1028  ALOGD("%s {%lld, %lld, %lld}  0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
1029        LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
1030}
1031
1032void rsDebug(const char *s, const long4 *c) {
1033  long4 ll = *c;
1034  ALOGD("%s {%lld, %lld, %lld, %lld}  0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
1035        LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
1036}
1037
1038void rsDebug(const char *s, unsigned long l) {
1039  unsigned long long ll = l;
1040  ALOGD("%s %llu  0x%llx", s, ll, ll);
1041}
1042
1043void rsDebug(const char *s, unsigned long long ll) {
1044  ALOGD("%s %llu  0x%llx", s, ll, ll);
1045}
1046
1047void rsDebug(const char *s, const ulong2 *c) {
1048  ulong2 ll = *c;
1049  ALOGD("%s {%llu, %llu}  0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
1050        LLu(ll.y));
1051}
1052
1053void rsDebug(const char *s, const ulong3 *c) {
1054  ulong3 ll = *c;
1055  ALOGD("%s {%llu, %llu, %llu}  0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
1056        LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
1057}
1058
1059void rsDebug(const char *s, const ulong4 *c) {
1060  ulong4 ll = *c;
1061  ALOGD("%s {%llu, %llu, %llu, %llu}  0x%llx 0x%llx 0x%llx 0x%llx", s,
1062        LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
1063        LLu(ll.z), LLu(ll.w));
1064}
1065
1066// FIXME: We need to export these function signatures for the compatibility
1067// library. The C++ name mangling that LLVM uses for ext_vector_type requires
1068// different versions for "long" vs. "long long". Note that the called
1069// functions are still using the appropriate 64-bit sizes.
1070
1071#ifndef __LP64__
1072typedef long l2 __attribute__((ext_vector_type(2)));
1073typedef long l3 __attribute__((ext_vector_type(3)));
1074typedef long l4 __attribute__((ext_vector_type(4)));
1075typedef unsigned long ul2 __attribute__((ext_vector_type(2)));
1076typedef unsigned long ul3 __attribute__((ext_vector_type(3)));
1077typedef unsigned long ul4 __attribute__((ext_vector_type(4)));
1078
1079void rsDebug(const char *s, const l2 *c) {
1080  long2 ll = *(const long2 *)c;
1081  ALOGD("%s {%lld, %lld}  0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
1082        LL(ll.y));
1083}
1084
1085void rsDebug(const char *s, const l3 *c) {
1086  long3 ll = *(const long3 *)c;
1087  ALOGD("%s {%lld, %lld, %lld}  0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
1088        LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
1089}
1090
1091void rsDebug(const char *s, const l4 *c) {
1092  long4 ll = *(const long4 *)c;
1093  ALOGD("%s {%lld, %lld, %lld, %lld}  0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
1094        LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
1095}
1096
1097void rsDebug(const char *s, const ul2 *c) {
1098  ulong2 ll = *(const ulong2 *)c;
1099  ALOGD("%s {%llu, %llu}  0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
1100        LLu(ll.y));
1101}
1102
1103void rsDebug(const char *s, const ul3 *c) {
1104  ulong3 ll = *(const ulong3 *)c;
1105  ALOGD("%s {%llu, %llu, %llu}  0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
1106        LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
1107}
1108
1109void rsDebug(const char *s, const ul4 *c) {
1110  ulong4 ll = *(const ulong4 *)c;
1111  ALOGD("%s {%llu, %llu, %llu, %llu}  0x%llx 0x%llx 0x%llx 0x%llx", s,
1112        LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
1113        LLu(ll.z), LLu(ll.w));
1114}
1115#endif
1116
1117void rsDebug(const char *s, const long2 ll) {
1118  ALOGD("%s {%lld, %lld}  0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
1119        LL(ll.y));
1120}
1121
1122void rsDebug(const char *s, const long3 ll) {
1123  ALOGD("%s {%lld, %lld, %lld}  0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
1124        LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
1125}
1126
1127void rsDebug(const char *s, const long4 ll) {
1128  ALOGD("%s {%lld, %lld, %lld, %lld}  0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
1129        LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
1130}
1131
1132void rsDebug(const char *s, const ulong2 ll) {
1133  ALOGD("%s {%llu, %llu}  0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
1134        LLu(ll.y));
1135}
1136
1137void rsDebug(const char *s, const ulong3 ll) {
1138  ALOGD("%s {%llu, %llu, %llu}  0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
1139        LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
1140}
1141
1142void rsDebug(const char *s, const ulong4 ll) {
1143  ALOGD("%s {%llu, %llu, %llu, %llu}  0x%llx 0x%llx 0x%llx 0x%llx", s,
1144        LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
1145        LLu(ll.z), LLu(ll.w));
1146}
1147
1148void rsDebug(const char *s, const void *p) { ALOGD("%s %p", s, p); }
1149