1709a0978ae141198018ca9769f8d96292a8928e6Jason Sams/*
2709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * Copyright (C) 2011-2012 The Android Open Source Project
3709a0978ae141198018ca9769f8d96292a8928e6Jason Sams *
4709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * you may not use this file except in compliance with the License.
6709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * You may obtain a copy of the License at
79ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet *
8709a0978ae141198018ca9769f8d96292a8928e6Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9709a0978ae141198018ca9769f8d96292a8928e6Jason Sams *
10709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * Unless required by applicable law or agreed to in writing, software
11709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * See the License for the specific language governing permissions and
14709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * limitations under the License.
15709a0978ae141198018ca9769f8d96292a8928e6Jason Sams */
16709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
17709a0978ae141198018ca9769f8d96292a8928e6Jason Sams#include "rsCpuCore.h"
18709a0978ae141198018ca9769f8d96292a8928e6Jason Sams#include "rsCpuScript.h"
192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include "rsCpuExecutable.h"
20709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
21110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifdef RS_COMPATIBILITY_LIB
22110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    #include <stdio.h>
23ee48c0bbf290a73e2cd4710b70d62fc203dac0dcStephen Hines    #include <sys/stat.h>
24c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines    #include <unistd.h>
25110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else
262fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar    #include "rsCppUtils.h"
272fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar
2882e0a6779cb1006921153081fb33374197e7c9deStephen Hines    #include <bcc/Config/Config.h>
29b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    #include <bcinfo/MetadataExtractor.h>
30ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines    #include <cutils/properties.h>
31b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines
32aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    #include <zlib.h>
33aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    #include <sys/file.h>
34b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    #include <sys/types.h>
35b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    #include <unistd.h>
36005113297b19ed256b6db9d6bc293ed9266899fcStephen Hines
37005113297b19ed256b6db9d6bc293ed9266899fcStephen Hines    #include <string>
38005113297b19ed256b6db9d6bc293ed9266899fcStephen Hines    #include <vector>
39110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif
40709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
41dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#include <set>
42dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#include <string>
43dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#include <dlfcn.h>
44dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#include <stdlib.h>
45dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#include <string.h>
46dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#include <iostream>
47cb17015fed6b11a5028f31cc804a3847e379945dYang Ni#include <sstream>
48dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar
49ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hinesnamespace {
508409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
518409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hinesstatic const bool kDebugGlobalVariables = false;
528409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
5314ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Walastatic bool allocationLODIsNull(const android::renderscript::Allocation *alloc) {
5414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala  // Even if alloc != nullptr, mallocPtr could be null if
5514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala  // IO_OUTPUT/IO_INPUT with no bound surface.
5614ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala  return alloc && alloc->mHal.drvState.lod[0].mallocPtr == nullptr;
5714ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala}
5814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala
59dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#ifndef RS_COMPATIBILITY_LIB
60dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar
61ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hinesstatic bool is_force_recompile() {
62ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines#ifdef RS_SERVER
63ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  return false;
64ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines#else
65ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  char buf[PROPERTY_VALUE_MAX];
66ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines
67ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  // Re-compile if floating point precision has been overridden.
68ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  property_get("debug.rs.precision", buf, "");
69ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  if (buf[0] != '\0') {
70ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines    return true;
71ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  }
72ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines
73ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  // Re-compile if debug.rs.forcerecompile is set.
74ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  property_get("debug.rs.forcerecompile", buf, "0");
75ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
76ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines    return true;
77ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  } else {
78ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines    return false;
79ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines  }
80ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines#endif  // RS_SERVER
81ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines}
82b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines
836847e73314e13aa02231268cca245a81eb0539caChris Wailesstatic void setCompileArguments(std::vector<const char*>* args,
846847e73314e13aa02231268cca245a81eb0539caChris Wailes                                const std::string& bcFileName,
856847e73314e13aa02231268cca245a81eb0539caChris Wailes                                const char* cacheDir, const char* resName,
866847e73314e13aa02231268cca245a81eb0539caChris Wailes                                const char* core_lib, bool useRSDebugContext,
878409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines                                const char* bccPluginName, bool emitGlobalInfo,
88f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham                                int optLevel, bool emitGlobalInfoSkipConstant) {
8940e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    rsAssert(cacheDir && resName && core_lib);
90da0f069871343119251d6b0586be356dc2146a62Yang Ni    args->push_back(android::renderscript::RsdCpuScriptImpl::BCC_EXE_PATH);
91687cfe85c3cffb244a7e5daeb1231f441a1ed54dTim Murray    args->push_back("-unroll-runtime");
92687cfe85c3cffb244a7e5daeb1231f441a1ed54dTim Murray    args->push_back("-scalarize-load-store");
938409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    if (emitGlobalInfo) {
948409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        args->push_back("-rs-global-info");
958409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        if (emitGlobalInfoSkipConstant) {
968409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines            args->push_back("-rs-global-info-skip-constant");
978409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        }
988409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    }
9940e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back("-o");
10040e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back(resName);
10140e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back("-output_path");
10240e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back(cacheDir);
10340e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back("-bclib");
10440e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back(core_lib);
10540e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back("-mtriple");
10640e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    args->push_back(DEFAULT_TARGET_TRIPLE_STRING);
107f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham    args->push_back("-O");
108f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham
109f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham    switch (optLevel) {
110a7481b21c4ad4127f54c02c7402039d068948a34Yang Ni    case 0:
111f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham        args->push_back("0");
112f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham        break;
113a7481b21c4ad4127f54c02c7402039d068948a34Yang Ni    case 3:
114f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham        args->push_back("3");
115f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham        break;
116f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham    default:
117f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham        ALOGW("Expected optimization level of 0 or 3. Received %d", optLevel);
118f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham        args->push_back("3");
119f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham        break;
120f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham    }
12140e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet
122358ffb84f56929cd2d61f6429a790a1606eaf865Tim Murray    // Enable workaround for A53 codegen by default.
123358ffb84f56929cd2d61f6429a790a1606eaf865Tim Murray#if defined(__aarch64__) && !defined(DISABLE_A53_WORKAROUND)
124358ffb84f56929cd2d61f6429a790a1606eaf865Tim Murray    args->push_back("-aarch64-fix-cortex-a53-835769");
125358ffb84f56929cd2d61f6429a790a1606eaf865Tim Murray#endif
126358ffb84f56929cd2d61f6429a790a1606eaf865Tim Murray
12740e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    // Execute the bcc compiler.
12840e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    if (useRSDebugContext) {
12940e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet        args->push_back("-rs-debug-ctx");
13040e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    } else {
13140e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet        // Only load additional libraries for compiles that don't use
13240e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet        // the debug context.
13340e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet        if (bccPluginName && strlen(bccPluginName) > 0) {
13440e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet            args->push_back("-load");
13540e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet            args->push_back(bccPluginName);
13640e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet        }
13740e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    }
13840e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet
13945e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines    args->push_back("-fPIC");
14045e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines    args->push_back("-embedRSInfo");
141dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar
1426847e73314e13aa02231268cca245a81eb0539caChris Wailes    args->push_back(bcFileName.c_str());
14344bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    args->push_back(nullptr);
14440e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet}
14540e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet
1466847e73314e13aa02231268cca245a81eb0539caChris Wailesstatic bool compileBitcode(const std::string &bcFileName,
147b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines                           const char *bitcode,
148b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines                           size_t bitcodeSize,
1492fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar                           std::vector<const char *> &compileArguments) {
15040e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    rsAssert(bitcode && bitcodeSize);
15140e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet
1526847e73314e13aa02231268cca245a81eb0539caChris Wailes    FILE *bcfile = fopen(bcFileName.c_str(), "w");
153b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    if (!bcfile) {
1546847e73314e13aa02231268cca245a81eb0539caChris Wailes        ALOGE("Could not write to %s", bcFileName.c_str());
155b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines        return false;
156b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    }
157b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
158b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    fclose(bcfile);
159b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    if (nwritten != bitcodeSize) {
160b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines        ALOGE("Could not write %zu bytes to %s", bitcodeSize,
1616847e73314e13aa02231268cca245a81eb0539caChris Wailes              bcFileName.c_str());
162b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines        return false;
163b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    }
164b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines
1652fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar    return android::renderscript::rsuExecuteCommand(
1662fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar                   android::renderscript::RsdCpuScriptImpl::BCC_EXE_PATH,
1672fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar                   compileArguments.size()-1, compileArguments.data());
168b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines}
169b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines
1706a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// The checksum is unnecessary under a few conditions, since the primary
1716a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// use-case for it is debugging. If we are loading something from the
1726a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// system partition (read-only), we know that it was precompiled as part of
1736a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// application ahead of time (and thus the checksum is completely
1746a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// unnecessary). The checksum is also unnecessary on release (non-debug)
1756a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// builds, as the only way to get a shared object is to have compiled the
1766a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// script once already. On a release build, there is no way to adjust the
1776a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// other libraries/dependencies, and so the only reason to recompile would
1786a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// be for a source APK change or an OTA. In either case, the APK would be
1796a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines// reinstalled, which would already clear the code_cache/ directory.
1806a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hinesbool isChecksumNeeded(const char *cacheDir) {
1816a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines    if ((::strcmp(SYSLIBPATH, cacheDir) == 0) ||
1826a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines        (::strcmp(SYSLIBPATH_VENDOR, cacheDir) == 0))
1836a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines        return false;
184aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    char buf[PROPERTY_VALUE_MAX];
185aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    property_get("ro.debuggable", buf, "");
186aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    return (buf[0] == '1');
187aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar}
188aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
189f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Nibool addFileToChecksum(const char *fileName, uint32_t &checksum) {
190f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    int FD = open(fileName, O_RDONLY);
191f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    if (FD == -1) {
192f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        ALOGE("Cannot open file \'%s\' to compute checksum", fileName);
193f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        return false;
194f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    }
195f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni
196f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    char buf[256];
197f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    while (true) {
198f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        ssize_t nread = read(FD, buf, sizeof(buf));
199f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        if (nread < 0) { // bail out on failed read
200f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni            ALOGE("Error while computing checksum for file \'%s\'", fileName);
201f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni            return false;
202f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        }
203f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni
204f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        checksum = adler32(checksum, (const unsigned char *) buf, nread);
205f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        if (static_cast<size_t>(nread) < sizeof(buf)) // EOF
206f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni            break;
207f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    }
208f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni
2092df576745c52a04a42d615f83b03f19d803b7757Elliott Hughes    if (close(FD) != 0) {
210f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        ALOGE("Cannot close file \'%s\' after computing checksum", fileName);
211f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni        return false;
212f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    }
213f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni    return true;
214f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni}
215cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
216cb17015fed6b11a5028f31cc804a3847e379945dYang Ni#endif  // !defined(RS_COMPATIBILITY_LIB)
217cb17015fed6b11a5028f31cc804a3847e379945dYang Ni}  // namespace
218cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
219cb17015fed6b11a5028f31cc804a3847e379945dYang Ninamespace android {
220cb17015fed6b11a5028f31cc804a3847e379945dYang Ninamespace renderscript {
221cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
222cb17015fed6b11a5028f31cc804a3847e379945dYang Ni#ifndef RS_COMPATIBILITY_LIB
223cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
224cb17015fed6b11a5028f31cc804a3847e379945dYang Niuint32_t constructBuildChecksum(uint8_t const *bitcode, size_t bitcodeSize,
225cb17015fed6b11a5028f31cc804a3847e379945dYang Ni                                const char *commandLine,
226cb17015fed6b11a5028f31cc804a3847e379945dYang Ni                                const char** bccFiles, size_t numFiles) {
227cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    uint32_t checksum = adler32(0L, Z_NULL, 0);
228cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
229cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    // include checksum of bitcode
230cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    if (bitcode != nullptr && bitcodeSize > 0) {
231cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        checksum = adler32(checksum, bitcode, bitcodeSize);
232cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    }
233cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
234cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    // include checksum of command line arguments
235cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    checksum = adler32(checksum, (const unsigned char *) commandLine,
236cb17015fed6b11a5028f31cc804a3847e379945dYang Ni                       strlen(commandLine));
237cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
238cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    // include checksum of bccFiles
239cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    for (size_t i = 0; i < numFiles; i++) {
240cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        const char* bccFile = bccFiles[i];
241cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        if (bccFile[0] != 0 && !addFileToChecksum(bccFile, checksum)) {
242cb17015fed6b11a5028f31cc804a3847e379945dYang Ni            // return empty checksum instead of something partial/corrupt
243cb17015fed6b11a5028f31cc804a3847e379945dYang Ni            return 0;
244cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        }
245cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    }
246cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
247cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    return checksum;
248cb17015fed6b11a5028f31cc804a3847e379945dYang Ni}
249cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
250f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni#endif  // !RS_COMPATIBILITY_LIB
251f02a2b0a2749d4a4f07edbc23eddff2e51d11b72Yang Ni
252709a0978ae141198018ca9769f8d96292a8928e6Jason SamsRsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
253709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mCtx = ctx;
254709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mScript = s;
255709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
25644bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mScriptSO = nullptr;
257dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar
25844bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mRoot = nullptr;
25944bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mRootExpand = nullptr;
26044bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mInit = nullptr;
26144bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mFreeChildren = nullptr;
262d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    mScriptExec = nullptr;
263709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
26444bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mBoundAllocs = nullptr;
26544bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    mIntrinsicData = nullptr;
266709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mIsThreadable = true;
267aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
268cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    mBuildChecksum = 0;
269aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    mChecksumNeeded = false;
270709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
271709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
272dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainarbool RsdCpuScriptImpl::storeRSInfoFromSO() {
273aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    // The shared object may have an invalid build checksum.
274aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    // Validate and fail early.
275aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    mScriptExec = ScriptExecutable::createFromSharedObject(
2765e48002cc4a11e9ce63852a77488cfb9f6765c2bYang Ni            mScriptSO, mChecksumNeeded ? mBuildChecksum : 0);
277aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
278aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    if (mScriptExec == nullptr) {
279aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        return false;
280aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    }
281aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
282dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
283dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    if (mRoot) {
284dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar        //ALOGE("Found root(): %p", mRoot);
285dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    }
286dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
287dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    if (mRootExpand) {
288dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar        //ALOGE("Found root.expand(): %p", mRootExpand);
289dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    }
29014ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    mInit = (InitOrDtorFunc_t) dlsym(mScriptSO, "init");
291dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    if (mInit) {
292dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar        //ALOGE("Found init(): %p", mInit);
293dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    }
29414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    mFreeChildren = (InitOrDtorFunc_t) dlsym(mScriptSO, ".rs.dtor");
295dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    if (mFreeChildren) {
296dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar        //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
297dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    }
298dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar
299d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    size_t varCount = mScriptExec->getExportedVariableCount();
300d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    if (varCount > 0) {
301d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni        mBoundAllocs = new Allocation *[varCount];
302d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni        memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
303dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    }
304dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar
30568173de001c5d41c74828a426651e07cfd9e8710Pirama Arumuga Nainar    mIsThreadable = mScriptExec->getThreadable();
30668173de001c5d41c74828a426651e07cfd9e8710Pirama Arumuga Nainar    //ALOGE("Script isThreadable? %d", mIsThreadable);
30768173de001c5d41c74828a426651e07cfd9e8710Pirama Arumuga Nainar
3088409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    if (kDebugGlobalVariables) {
3098409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        mScriptExec->dumpGlobalInfo();
3108409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    }
3118409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
312d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    return true;
313d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni}
314d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni
315709a0978ae141198018ca9769f8d96292a8928e6Jason Samsbool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
316709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                            uint8_t const *bitcode, size_t bitcodeSize,
317005113297b19ed256b6db9d6bc293ed9266899fcStephen Hines                            uint32_t flags, char const *bccPluginName) {
318e8f9fba78f0cb79fa8773373a635e30382113a75Yang Ni    //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir,
319e8f9fba78f0cb79fa8773373a635e30382113a75Yang Ni    // bitcode, bitcodeSize, flags, lookupFunc);
320709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    //ALOGE("rsdScriptInit %p %p", rsc, script);
321709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
322709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mCtx->lockMutex();
323110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB
324005113297b19ed256b6db9d6bc293ed9266899fcStephen Hines    bool useRSDebugContext = false;
325709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
32640e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize);
32740e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    if (!bitcodeMetadata.extract()) {
328b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines        ALOGE("Could not extract metadata from bitcode");
329f94e8db4232979b2fc93e8a77c42bfa57d3da56aStephen Hines        mCtx->unlockMutex();
330b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines        return false;
331b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines    }
332b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines
33340e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize);
334cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines
335cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines    if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
336005113297b19ed256b6db9d6bc293ed9266899fcStephen Hines        useRSDebugContext = true;
337ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines    }
338ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines
339f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham    int optLevel = mCtx->getContext()->getOptLevel();
340f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham
3416847e73314e13aa02231268cca245a81eb0539caChris Wailes    std::string bcFileName(cacheDir);
34240e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    bcFileName.append("/");
34340e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    bcFileName.append(resName);
34440e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    bcFileName.append(".bc");
34540e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet
34640e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    std::vector<const char*> compileArguments;
3478409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    bool emitGlobalInfo = mCtx->getEmbedGlobalInfo();
3488409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    bool emitGlobalInfoSkipConstant = mCtx->getEmbedGlobalInfoSkipConstant();
34940e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
3508409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines                        useRSDebugContext, bccPluginName, emitGlobalInfo,
351f5029803ae6ce9d92d70b76e7a7cdd8d484f31caverena beckham                        optLevel, emitGlobalInfoSkipConstant);
352aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
3536a236ad3a3760e8124b68a1b6220ed6e4fbfb152Stephen Hines    mChecksumNeeded = isChecksumNeeded(cacheDir);
354aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    if (mChecksumNeeded) {
355aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        std::vector<const char *> bccFiles = { BCC_EXE_PATH,
356aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar                                               core_lib,
357aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar                                             };
3582fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar
3592fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar        // The last argument of compileArguments is a nullptr, so remove 1 from
3602fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar        // the size.
3612fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar        std::unique_ptr<const char> compileCommandLine(
3622fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar            rsuJoinStrings(compileArguments.size()-1, compileArguments.data()));
3632fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar
364aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        mBuildChecksum = constructBuildChecksum(bitcode, bitcodeSize,
365aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar                                                compileCommandLine.get(),
366cb17015fed6b11a5028f31cc804a3847e379945dYang Ni                                                bccFiles.data(), bccFiles.size());
367aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
368cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        if (mBuildChecksum == 0) {
369aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            // cannot compute checksum but verification is enabled
370aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            mCtx->unlockMutex();
371aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            return false;
372aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        }
373aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    }
374aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    else {
375aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        // add a dummy/constant as a checksum if verification is disabled
376cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        mBuildChecksum = 0xabadcafe;
377aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    }
378aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
379aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    // Append build checksum to commandline
380aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    // Handle the terminal nullptr in compileArguments
381aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    compileArguments.pop_back();
382aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    compileArguments.push_back("-build-checksum");
383cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    std::stringstream ss;
384cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    ss << std::hex << mBuildChecksum;
385cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    compileArguments.push_back(ss.str().c_str());
386aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    compileArguments.push_back(nullptr);
387aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
388bf96a520e162b503b293f65ca9ca9be66d4a0036Tim Murray    if (!is_force_recompile() && !useRSDebugContext) {
3891c44cb6b1133730cd18929d637e71e9326c70bd0Yang Ni        mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName);
390aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
391aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        // Read RS info from the shared object to detect checksum mismatch
392aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        if (mScriptSO != nullptr && !storeRSInfoFromSO()) {
393aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            dlclose(mScriptSO);
394aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            mScriptSO = nullptr;
395aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        }
396cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines    }
397709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
39840e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    // If we can't, it's either not there or out of date.  We compile the bit code and try loading
39940e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet    // again.
40045e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines    if (mScriptSO == nullptr) {
40145e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines        if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize,
4022fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar                            compileArguments))
40345e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines        {
40440e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet            ALOGE("bcc: FAILS to compile '%s'", resName);
40540e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet            mCtx->unlockMutex();
40640e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet            return false;
40740e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet        }
40845e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines
4094c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines        if (!SharedLibraryUtils::createSharedLibrary(mCtx->getContext()->getDriverName(),
4104c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines                                                     cacheDir, resName)) {
41145e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines            ALOGE("Linker: Failed to link object file '%s'", resName);
41245e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines            mCtx->unlockMutex();
41345e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines            return false;
41445e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines        }
41545e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines
4161c44cb6b1133730cd18929d637e71e9326c70bd0Yang Ni        mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName);
41745e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines        if (mScriptSO == nullptr) {
41845e753a46e587c69b3b0d0c5138e88715a24a29aStephen Hines            ALOGE("Unable to load '%s'", resName);
41940e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet            mCtx->unlockMutex();
42040e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet            return false;
42140e35cdbe217ec8bf9fc3c69873c7d62fc14158fJean-Luc Brouillet        }
422aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
423aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        // Read RS symbol information from the .so.
424aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        if (!storeRSInfoFromSO()) {
425aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            goto error;
426aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        }
427709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
428709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
429c31585b8ca865bf2b35abc79c8a8ee42de27bee8Yang Ni    mBitcodeFilePath.setTo(bcFileName.c_str());
430da0f069871343119251d6b0586be356dc2146a62Yang Ni
431dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar#else  // RS_COMPATIBILITY_LIB is defined
432f3213d7fd648da98bb3b03204eaf90f03c31926bMiao Wang    const char *nativeLibDir = mCtx->getContext()->getNativeLibDir();
433f3213d7fd648da98bb3b03204eaf90f03c31926bMiao Wang    mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName, nativeLibDir);
434110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams
435dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    if (!mScriptSO) {
436dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar        goto error;
437dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    }
438110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams
439dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    if (!storeRSInfoFromSO()) {
440c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines        goto error;
441110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    }
442110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif
443709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mCtx->unlockMutex();
444709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    return true;
445110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams
446110f181b7966212a36ef18016f9b81c7322d0a2fJason Samserror:
447110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams
448110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    mCtx->unlockMutex();
449110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    if (mScriptSO) {
450110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams        dlclose(mScriptSO);
451eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        mScriptSO = nullptr;
452110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    }
453110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    return false;
454709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
455709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
4569ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet#ifndef RS_COMPATIBILITY_LIB
4579ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet
4589ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouilletconst char* RsdCpuScriptImpl::findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode,
4599ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet                                          size_t bitcodeSize) {
4609ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    const char* defaultLib = SYSLIBPATH"/libclcore.bc";
4619ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet
4629ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    // If we're debugging, use the debug library.
4639ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
4649ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        return SYSLIBPATH"/libclcore_debug.bc";
4659ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    }
4669ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet
467f7f9316f4cf373733285f947bea876ead7216715Verena Beckham    if (ME.hasDebugInfo()) {
468f7f9316f4cf373733285f947bea876ead7216715Verena Beckham        return SYSLIBPATH"/libclcore_g.bc";
469f7f9316f4cf373733285f947bea876ead7216715Verena Beckham    }
470f7f9316f4cf373733285f947bea876ead7216715Verena Beckham
4719ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    // If a callback has been registered to specify a library, use that.
4729ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
47344bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    if (selectRTCallback != nullptr) {
4749ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        return selectRTCallback((const char*)bitcode, bitcodeSize);
4759ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    }
4769ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet
4779ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    // Check for a platform specific library
4789ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet#if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_CLCORE_NEON)
4799ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
480f4d3836c83097f57b62c235910fbf490c56ddf56Jean-Luc Brouillet    if (prec == bcinfo::RS_FP_Relaxed) {
4819ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        // NEON-capable ARMv7a devices can use an accelerated math library
4829ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        // for all reduced precision scripts.
4839ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        // ARMv8 does not use NEON, as ASIMD can be used with all precision
4849ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        // levels.
4859ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        return SYSLIBPATH"/libclcore_neon.bc";
4869ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    } else {
4879ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet        return defaultLib;
4889ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    }
4899ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet#elif defined(__i386__) || defined(__x86_64__)
4909ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    // x86 devices will use an optimized library.
4919ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    return SYSLIBPATH"/libclcore_x86.bc";
4929ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet#else
4939ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet    return defaultLib;
4949ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet#endif
4959ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet}
4969ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet
4979ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet#endif
4989ab5094dd32352b33e251e540934f6e814c5fa5bJean-Luc Brouillet
499709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::populateScript(Script *script) {
500110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    // Copy info over to runtime
501d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    script->mHal.info.exportedFunctionCount = mScriptExec->getExportedFunctionCount();
50214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    script->mHal.info.exportedReduceCount = mScriptExec->getExportedReduceCount();
50314ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    script->mHal.info.exportedForEachCount = mScriptExec->getExportedForEachCount();
504d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    script->mHal.info.exportedVariableCount = mScriptExec->getExportedVariableCount();
505577194ac9c2bf10f31e564de91371764b265929aPirama Arumuga Nainar    script->mHal.info.exportedPragmaCount = mScriptExec->getPragmaCount();;
506e8f9fba78f0cb79fa8773373a635e30382113a75Yang Ni    script->mHal.info.exportedPragmaKeyList = mScriptExec->getPragmaKeys();
507e8f9fba78f0cb79fa8773373a635e30382113a75Yang Ni    script->mHal.info.exportedPragmaValueList = mScriptExec->getPragmaValues();
508110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams
509110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    // Bug, need to stash in metadata
510110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    if (mRootExpand) {
511110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams        script->mHal.info.root = mRootExpand;
512110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    } else {
513110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams        script->mHal.info.root = mRoot;
514110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    }
515709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
516709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
51714ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala// Set up the launch dimensions, and write the values of the launch
51814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala// dimensions into the mtls start/end fields.
51914ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala//
52014ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala// Inputs:
52114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala//    baseDim - base shape of the input
52214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala//         sc - used to constrain the launch dimensions
52314ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala//
52414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala// Returns:
52514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala//   True on success, false on failure to set up
52614ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Walabool RsdCpuScriptImpl::setUpMtlsDimensions(MTLaunchStructCommon *mtls,
52714ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                                           const RsLaunchDimensions &baseDim,
52814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                                           const RsScriptCall *sc) {
52914ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    rsAssert(mtls);
53014ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala
53114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala#define SET_UP_DIMENSION(DIM_FIELD, SC_FIELD) do {            \
53214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    if (!sc || (sc->SC_FIELD##End == 0)) {                    \
53314ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        mtls->end.DIM_FIELD = baseDim.DIM_FIELD;              \
53414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    } else {                                                  \
53514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        mtls->start.DIM_FIELD =                               \
53614ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala            rsMin(baseDim.DIM_FIELD, sc->SC_FIELD##Start);    \
53714ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        mtls->end.DIM_FIELD =                                 \
53814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala            rsMin(baseDim.DIM_FIELD, sc->SC_FIELD##End);      \
53914ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        if (mtls->start.DIM_FIELD >= mtls->end.DIM_FIELD) {   \
54014ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala            mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, \
54114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                "Failed to launch kernel; Invalid "           \
54214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                #SC_FIELD "Start or " #SC_FIELD "End.");      \
54314ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala            return false;                                     \
54414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        }                                                     \
54514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    }} while(0)
54614ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala
54714ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    SET_UP_DIMENSION(x, x);
54814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    SET_UP_DIMENSION(y, y);
54914ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    SET_UP_DIMENSION(z, z);
55087643a32d4eaefe349d3a81513fffe0c4e3e8a80Yang Ni    // Checks and setup of fields other than x, y, z are ignored, since those
55187643a32d4eaefe349d3a81513fffe0c4e3e8a80Yang Ni    // fields are not used in the runtime and are not visible in the Java API.
55214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala#undef SET_UP_DIMENSION
55314ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala
55414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    return true;
55514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala}
55614ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala
557ae2ec3febedfc29376b9104413fb4042028f1265David Gross// Preliminary work to prepare a general reduce-style kernel for launch.
558ae2ec3febedfc29376b9104413fb4042028f1265David Grossbool RsdCpuScriptImpl::reduceMtlsSetup(const Allocation ** ains,
559ae2ec3febedfc29376b9104413fb4042028f1265David Gross                                       uint32_t inLen,
560ae2ec3febedfc29376b9104413fb4042028f1265David Gross                                       const Allocation * aout,
56114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                                       const RsScriptCall *sc,
56214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                                       MTLaunchStructReduce *mtls) {
5636c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    rsAssert(ains && (inLen >= 1) && aout);
564ae2ec3febedfc29376b9104413fb4042028f1265David Gross    memset(mtls, 0, sizeof(MTLaunchStructReduce));
5656c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->dimPtr = &mtls->redp.dim;
5666c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5676c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    for (int index = inLen; --index >= 0;) {
5686c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (allocationLODIsNull(ains[index])) {
5696c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
5706c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                                         "reduce called with null in allocations");
5716c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            return false;
5726c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5736c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    }
5746c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5756c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    if (allocationLODIsNull(aout)) {
5766c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
5776c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                                     "reduce called with null out allocation");
5786c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        return false;
5796c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    }
5806c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5816c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    const Allocation *ain0   = ains[0];
5826c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    const Type       *inType = ain0->getType();
5836c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5846c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.dim.x = inType->getDimX();
5856c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.dim.y = inType->getDimY();
5866c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.dim.z = inType->getDimZ();
5876c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5886c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    for (int Index = inLen; --Index >= 1;) {
5896c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (!ain0->hasSameDims(ains[Index])) {
5906c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
5916c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                                         "Failed to launch reduction kernel;"
5926c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                                         "dimensions of input allocations do not match.");
5936c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            return false;
5946c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5956c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    }
5966c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5976c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    if (!setUpMtlsDimensions(mtls, mtls->redp.dim, sc)) {
5986c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        return false;
5996c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    }
6006c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
6016c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    // The X & Y walkers always want 0-1 min even if dim is not present
6026c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->end.x = rsMax((uint32_t)1, mtls->end.x);
6036c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->end.y = rsMax((uint32_t)1, mtls->end.y);
6046c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
6056c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->rs = mCtx;
6066c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
60710adb0c2029f112b5738228617d5645f6ecea0c5David Gross    mtls->mSliceNum    = 0;
60810adb0c2029f112b5738228617d5645f6ecea0c5David Gross    mtls->mSliceSize   = 1;
60910adb0c2029f112b5738228617d5645f6ecea0c5David Gross    mtls->isThreadable = mIsThreadable;
6106c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
6116c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    // Set up output,
6126c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.outLen = 1;
6136c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.outPtr[0] = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
6146c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.outStride[0] = aout->getType()->getElementSizeBytes();
6156c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
6166c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    // Set up input.
6176c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    memcpy(mtls->ains, ains, inLen * sizeof(ains[0]));
6186c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.inLen = inLen;
6196c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    for (int index = inLen; --index >= 0;) {
6206c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        mtls->redp.inPtr[index] = (const uint8_t*)ains[index]->mHal.drvState.lod[0].mallocPtr;
6216c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        mtls->redp.inStride[index] = ains[index]->getType()->getElementSizeBytes();
6226c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    }
6236c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
6246c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    // All validation passed, ok to launch threads
6256c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    return true;
6266c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross}
6276c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
62814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala// Preliminary work to prepare a forEach-style kernel for launch.
629bf2111d3b3de310932099514f06924e48fa1d7b2Jason Samsbool RsdCpuScriptImpl::forEachMtlsSetup(const Allocation ** ains,
630f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                        uint32_t inLen,
631f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                        Allocation * aout,
632709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                        const void * usr, uint32_t usrLen,
633709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                        const RsScriptCall *sc,
63414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                                        MTLaunchStructForEach *mtls) {
635838c2d0dc0b8b07d4aa8de4360765738c6d2770eMiao Wang    if (ains == nullptr && inLen != 0) {
636838c2d0dc0b8b07d4aa8de4360765738c6d2770eMiao Wang        mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
637838c2d0dc0b8b07d4aa8de4360765738c6d2770eMiao Wang          "rsForEach called with none-zero inLen with null in allocations");
638838c2d0dc0b8b07d4aa8de4360765738c6d2770eMiao Wang        return false;
639838c2d0dc0b8b07d4aa8de4360765738c6d2770eMiao Wang    }
640838c2d0dc0b8b07d4aa8de4360765738c6d2770eMiao Wang
64114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    memset(mtls, 0, sizeof(MTLaunchStructForEach));
64214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    mtls->dimPtr = &mtls->fep.dim;
643709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
644f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes    for (int index = inLen; --index >= 0;) {
64514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        if (allocationLODIsNull(ains[index])) {
6464b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes            mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
647f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                         "rsForEach called with null in allocations");
648bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams            return false;
6494b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        }
6504b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    }
6514b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
65214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    if (allocationLODIsNull(aout)) {
653f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes        mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
654f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                     "rsForEach called with null out allocations");
655bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams        return false;
6564b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    }
6574b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
658f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes    if (inLen > 0) {
6594b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        const Allocation *ain0   = ains[0];
6604b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        const Type       *inType = ain0->getType();
6614b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
662c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.dim.x = inType->getDimX();
663c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.dim.y = inType->getDimY();
664c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.dim.z = inType->getDimZ();
6654b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
6664b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        for (int Index = inLen; --Index >= 1;) {
6674b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes            if (!ain0->hasSameDims(ains[Index])) {
6684b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes                mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
6696c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                  "Failed to launch kernel; dimensions of input"
670e8f9fba78f0cb79fa8773373a635e30382113a75Yang Ni                  "allocations do not match.");
671bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams                return false;
6724b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes            }
6734b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        }
67444bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    } else if (aout != nullptr) {
6754b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        const Type *outType = aout->getType();
6764b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
677c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.dim.x = outType->getDimX();
678c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.dim.y = outType->getDimY();
679c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.dim.z = outType->getDimZ();
6804b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
681a9139c724f8312b3634d213599f2d6b3b2505db2Jason Sams    } else if (sc != nullptr) {
682a9139c724f8312b3634d213599f2d6b3b2505db2Jason Sams        mtls->fep.dim.x = sc->xEnd;
683a9139c724f8312b3634d213599f2d6b3b2505db2Jason Sams        mtls->fep.dim.y = sc->yEnd;
684a9139c724f8312b3634d213599f2d6b3b2505db2Jason Sams        mtls->fep.dim.z = 0;
6854b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    } else {
686f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes        mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
687f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                     "rsForEach called with null allocations");
688bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams        return false;
6894b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    }
6904b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
69144bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    if (inLen > 0 && aout != nullptr) {
6924b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        if (!ains[0]->hasSameDims(aout)) {
6934b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes            mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
6944b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes              "Failed to launch kernel; dimensions of input and output allocations do not match.");
6954b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
696bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams            return false;
6974b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        }
6984b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    }
6994b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
70014ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    if (!setUpMtlsDimensions(mtls, mtls->fep.dim, sc)) {
70114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        return false;
702bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    }
703bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams
704bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    // The X & Y walkers always want 0-1 min even if dim is not present
705bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    mtls->end.x    = rsMax((uint32_t)1, mtls->end.x);
706bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    mtls->end.y    = rsMax((uint32_t)1, mtls->end.y);
70714ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    mtls->rs       = mCtx;
708c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams    if (ains) {
709c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        memcpy(mtls->ains, ains, inLen * sizeof(ains[0]));
710c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams    }
711c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams    mtls->aout[0]    = aout;
7124b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    mtls->fep.usr    = usr;
7134b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    mtls->fep.usrLen = usrLen;
7144b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    mtls->mSliceSize = 1;
7154b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    mtls->mSliceNum  = 0;
7164b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
7174b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    mtls->isThreadable  = mIsThreadable;
7184b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
719f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes    if (inLen > 0) {
720f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes        mtls->fep.inLen = inLen;
7214b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        for (int index = inLen; --index >= 0;) {
722c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams            mtls->fep.inPtr[index] = (const uint8_t*)ains[index]->mHal.drvState.lod[0].mallocPtr;
723c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams            mtls->fep.inStride[index] = ains[index]->getType()->getElementSizeBytes();
7244b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes        }
7254b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    }
7264b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
72744bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    if (aout != nullptr) {
728c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.outPtr[0] = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
729c0d68470b978a79ce024fde56f23ea3690603ccdJason Sams        mtls->fep.outStride[0] = aout->getType()->getElementSizeBytes();
7304b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes    }
731bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams
732bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    // All validation passed, ok to launch threads
733bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    return true;
7344b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes}
7354b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
736709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
737709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeForEach(uint32_t slot,
738f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                     const Allocation ** ains,
739f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                     uint32_t inLen,
740709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                     Allocation * aout,
741709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                     const void * usr,
742709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                     uint32_t usrLen,
743709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                     const RsScriptCall *sc) {
744709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
74514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    MTLaunchStructForEach mtls;
7464b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
747bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    if (forEachMtlsSetup(ains, inLen, aout, usr, usrLen, sc, &mtls)) {
748bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams        forEachKernelSetup(slot, &mtls);
7494b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
750bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams        RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
75114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala        mCtx->launchForEach(ains, inLen, aout, sc, &mtls);
752bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams        mCtx->setTLS(oldTLS);
753bf2111d3b3de310932099514f06924e48fa1d7b2Jason Sams    }
7544b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes}
7554b3c34e6833e39bc89c2128002806b654b8e623dChris Wailes
75614ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Walavoid RsdCpuScriptImpl::invokeReduce(uint32_t slot,
757ae2ec3febedfc29376b9104413fb4042028f1265David Gross                                    const Allocation ** ains, uint32_t inLen,
75814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                                    Allocation *aout,
75914ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala                                    const RsScriptCall *sc) {
760ae2ec3febedfc29376b9104413fb4042028f1265David Gross  MTLaunchStructReduce mtls;
76114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala
762ae2ec3febedfc29376b9104413fb4042028f1265David Gross  if (reduceMtlsSetup(ains, inLen, aout, sc, &mtls)) {
763ae2ec3febedfc29376b9104413fb4042028f1265David Gross    reduceKernelSetup(slot, &mtls);
7646c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    RsdCpuScriptImpl *oldTLS = mCtx->setTLS(this);
765ae2ec3febedfc29376b9104413fb4042028f1265David Gross    mCtx->launchReduce(ains, inLen, aout, &mtls);
7666c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mCtx->setTLS(oldTLS);
7676c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross  }
7686c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross}
7696c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
77014ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Walavoid RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStructForEach *mtls) {
771709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mtls->script = this;
772709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mtls->fep.slot = slot;
773d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    mtls->kernel = mScriptExec->getForEachFunction(slot);
77444bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    rsAssert(mtls->kernel != nullptr);
775709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
776709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
77714ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Walavoid RsdCpuScriptImpl::reduceKernelSetup(uint32_t slot, MTLaunchStructReduce *mtls) {
77814ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    mtls->script = this;
7796c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->redp.slot = slot;
7806c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
781ae2ec3febedfc29376b9104413fb4042028f1265David Gross    const ReduceDescription *desc = mScriptExec->getReduceDescription(slot);
7826c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->accumFunc = desc->accumFunc;
7836c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->initFunc  = desc->initFunc;   // might legally be nullptr
78410adb0c2029f112b5738228617d5645f6ecea0c5David Gross    mtls->combFunc  = desc->combFunc;   // might legally be nullptr
7856c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->outFunc   = desc->outFunc;    // might legally be nullptr
7866c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    mtls->accumSize = desc->accumSize;
7876c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
7886c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    rsAssert(mtls->accumFunc != nullptr);
7896c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross}
7906c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
791709a0978ae141198018ca9769f8d96292a8928e6Jason Samsint RsdCpuScriptImpl::invokeRoot() {
792709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
793709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    int ret = mRoot();
794709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mCtx->setTLS(oldTLS);
795709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    return ret;
796709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
797709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
798709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeInit() {
799709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (mInit) {
800709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        mInit();
801709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
802709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
803709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
804709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeFreeChildren() {
805709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (mFreeChildren) {
806709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        mFreeChildren();
807709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
808709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
809709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
810709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
811709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                      size_t paramLength) {
812dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    //ALOGE("invoke %i %p %zu", slot, params, paramLength);
813eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen    void * ap = nullptr;
814eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen
815eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen#if defined(__x86_64__)
816eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen    // The invoked function could have input parameter of vector type for example float4 which
817eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen    // requires void* params to be 16 bytes aligned when using SSE instructions for x86_64 platform.
818eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen    // So try to align void* params before passing them into RS exported function.
819eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen
820eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen    if ((uint8_t)(uint64_t)params & 0x0F) {
821eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen        if ((ap = (void*)memalign(16, paramLength)) != nullptr) {
822eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen            memcpy(ap, params, paramLength);
823eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen        } else {
824e8f9fba78f0cb79fa8773373a635e30382113a75Yang Ni            ALOGE("x86_64: invokeFunction memalign error, still use params which"
825e8f9fba78f0cb79fa8773373a635e30382113a75Yang Ni                  " is not 16 bytes aligned.");
826eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen        }
827eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen    }
828eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen#endif
829709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
830709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
831dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    reinterpret_cast<void (*)(const void *, uint32_t)>(
832d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni        mScriptExec->getInvokeFunction(slot))(ap? (const void *) ap: params, paramLength);
833eaba5a3ca215729258dcf9ac6f0bb5f88c78f998Yong Chen
834c246d91e490df18899490931469d277064070a63Yong Chen#if defined(__x86_64__)
835c246d91e490df18899490931469d277064070a63Yong Chen    free(ap);
836c246d91e490df18899490931469d277064070a63Yong Chen#endif
837c246d91e490df18899490931469d277064070a63Yong Chen
838709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mCtx->setTLS(oldTLS);
839709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
840709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
841709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
842709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    //rsAssert(!script->mFieldIsObject[slot]);
843dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    //ALOGE("setGlobalVar %i %p %zu", slot, data, dataLength);
844709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
845709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    //if (mIntrinsicID) {
846709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
847709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        //return;
848709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    //}
849709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
850d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
851709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (!destPtr) {
852709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        //ALOGV("Calling setVar on slot = %i which is null", slot);
853709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        return;
854709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
855709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
856709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    memcpy(destPtr, data, dataLength);
857709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
858709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
8599c64239ebbfa4170190ede812e69150035e008e0Tim Murrayvoid RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
8609c64239ebbfa4170190ede812e69150035e008e0Tim Murray    //rsAssert(!script->mFieldIsObject[slot]);
861dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    //ALOGE("getGlobalVar %i %p %zu", slot, data, dataLength);
8629c64239ebbfa4170190ede812e69150035e008e0Tim Murray
863d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    int32_t *srcPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
8649c64239ebbfa4170190ede812e69150035e008e0Tim Murray    if (!srcPtr) {
8659c64239ebbfa4170190ede812e69150035e008e0Tim Murray        //ALOGV("Calling setVar on slot = %i which is null", slot);
8669c64239ebbfa4170190ede812e69150035e008e0Tim Murray        return;
8679c64239ebbfa4170190ede812e69150035e008e0Tim Murray    }
8689c64239ebbfa4170190ede812e69150035e008e0Tim Murray    memcpy(data, srcPtr, dataLength);
8699c64239ebbfa4170190ede812e69150035e008e0Tim Murray}
8709c64239ebbfa4170190ede812e69150035e008e0Tim Murray
8719c64239ebbfa4170190ede812e69150035e008e0Tim Murray
872709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
873709a0978ae141198018ca9769f8d96292a8928e6Jason Sams                                                const Element *elem,
874ac8d146a41f18afad5314ac8af440d6aedbe20bfStephen Hines                                                const uint32_t *dims, size_t dimLength) {
875d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
876709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (!destPtr) {
877709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        //ALOGV("Calling setVar on slot = %i which is null", slot);
878709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        return;
879709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
880709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
881709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    // We want to look at dimension in terms of integer components,
882709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    // but dimLength is given in terms of bytes.
883709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    dimLength /= sizeof(int);
884709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
885709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    // Only a single dimension is currently supported.
886709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    rsAssert(dimLength == 1);
887709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (dimLength == 1) {
888709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        // First do the increment loop.
889709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        size_t stride = elem->getSizeBytes();
890709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        const char *cVal = reinterpret_cast<const char *>(data);
891ac8d146a41f18afad5314ac8af440d6aedbe20bfStephen Hines        for (uint32_t i = 0; i < dims[0]; i++) {
892709a0978ae141198018ca9769f8d96292a8928e6Jason Sams            elem->incRefs(cVal);
893709a0978ae141198018ca9769f8d96292a8928e6Jason Sams            cVal += stride;
894709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        }
895709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
896709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        // Decrement loop comes after (to prevent race conditions).
897709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        char *oldVal = reinterpret_cast<char *>(destPtr);
898ac8d146a41f18afad5314ac8af440d6aedbe20bfStephen Hines        for (uint32_t i = 0; i < dims[0]; i++) {
899709a0978ae141198018ca9769f8d96292a8928e6Jason Sams            elem->decRefs(oldVal);
900709a0978ae141198018ca9769f8d96292a8928e6Jason Sams            oldVal += stride;
901709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        }
902709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
903709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
904709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    memcpy(destPtr, data, dataLength);
905709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
906709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
907709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
908709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
909709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    //rsAssert(!script->mFieldIsObject[slot]);
910dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    //ALOGE("setGlobalBind %i %p", slot, data);
911709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
912d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
913709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (!destPtr) {
914709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        //ALOGV("Calling setVar on slot = %i which is null", slot);
915709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        return;
916709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
917709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
91844bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    void *ptr = nullptr;
919709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    mBoundAllocs[slot] = data;
920dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    if (data) {
921709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        ptr = data->mHal.drvState.lod[0].mallocPtr;
922709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
923709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    memcpy(destPtr, &ptr, sizeof(void *));
924709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
925709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
926709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
927709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
928709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    //rsAssert(script->mFieldIsObject[slot]);
929dc0d8f7c0f1f43f25c34fbc04656ad578f6e953bPirama Arumuga Nainar    //ALOGE("setGlobalObj %i %p", slot, data);
930709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
931d9bae689c1b8c3f2ed1a5f2b374dc9393584b8ddYang Ni    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
932709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (!destPtr) {
933709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        //ALOGV("Calling setVar on slot = %i which is null", slot);
934709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        return;
935709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
936709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
93705ef73f2d934f1083cc3b8aeb33fe21de9d6e88fJason Sams    rsrSetObject(mCtx->getContext(), (rs_object_base *)destPtr, data);
938709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
939709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
940062c287f573ecc06c38ee4295e5627e12c52ac3dYang Niconst char* RsdCpuScriptImpl::getFieldName(uint32_t slot) const {
941062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    return mScriptExec->getFieldName(slot);
942062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni}
943062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
944709a0978ae141198018ca9769f8d96292a8928e6Jason SamsRsdCpuScriptImpl::~RsdCpuScriptImpl() {
9451efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    delete mScriptExec;
9461efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    delete[] mBoundAllocs;
947110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    if (mScriptSO) {
948110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams        dlclose(mScriptSO);
949110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams    }
950709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
951709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
952709a0978ae141198018ca9769f8d96292a8928e6Jason SamsAllocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
953709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    if (!ptr) {
95444bef6fba6244292b751387f3d6c31cca96c28adChris Wailes        return nullptr;
955709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
956709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
957709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
958709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        Allocation *a = mBoundAllocs[ct];
959709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        if (!a) continue;
960709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
961709a0978ae141198018ca9769f8d96292a8928e6Jason Sams            return a;
962709a0978ae141198018ca9769f8d96292a8928e6Jason Sams        }
963709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    }
964709a0978ae141198018ca9769f8d96292a8928e6Jason Sams    ALOGE("rsGetAllocation, failed to find %p", ptr);
96544bef6fba6244292b751387f3d6c31cca96c28adChris Wailes    return nullptr;
966709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
967709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
9688409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hinesint RsdCpuScriptImpl::getGlobalEntries() const {
9698409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    return mScriptExec->getGlobalEntries();
9708409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines}
9718409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
9728409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hinesconst char * RsdCpuScriptImpl::getGlobalName(int i) const {
9738409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    return mScriptExec->getGlobalName(i);
9748409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines}
9758409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
9768409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hinesconst void * RsdCpuScriptImpl::getGlobalAddress(int i) const {
9778409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    return mScriptExec->getGlobalAddress(i);
9788409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines}
9798409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
9808409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hinessize_t RsdCpuScriptImpl::getGlobalSize(int i) const {
9818409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    return mScriptExec->getGlobalSize(i);
9828409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines}
9838409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
9845aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hinesuint32_t RsdCpuScriptImpl::getGlobalProperties(int i) const {
9855aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    return mScriptExec->getGlobalProperties(i);
9865aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines}
9875aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines
988f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailesvoid RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation ** ains,
989f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                 uint32_t inLen, Allocation * aout,
990f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                 const void * usr, uint32_t usrLen,
991f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                 const RsScriptCall *sc) {}
99217e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams
993f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailesvoid RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation ** ains,
994f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                  uint32_t inLen, Allocation * aout,
995f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                  const void * usr, uint32_t usrLen,
996f37121300217d3b39ab66dd9c8881bcbcad932dfChris Wailes                                  const RsScriptCall *sc) {}
99717e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams
998709a0978ae141198018ca9769f8d96292a8928e6Jason Sams
999709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
1000709a0978ae141198018ca9769f8d96292a8928e6Jason Sams}
1001