rsScriptC.cpp revision 1d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24e
1326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams/*
2326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Copyright (C) 2009 The Android Open Source Project
3326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *
4326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * you may not use this file except in compliance with the License.
6326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * You may obtain a copy of the License at
7326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *
8326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *
10326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Unless required by applicable law or agreed to in writing, software
11326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * See the License for the specific language governing permissions and
14326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * limitations under the License.
15326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams */
16326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
17326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "rsContext.h"
18326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "rsScriptC.h"
19326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "rsMatrix.h"
20326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
211ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich#include "acc/acc.h"
229c4e4ca9ff75a7fe18544c83fcf782e46c9b6ac2Joe Onorato#include "utils/Timers.h"
231ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich
241aa5a4eb81b8b88aeb5d2b6f4c47356fd0a62923Jason Sams#include <GLES/gl.h>
251aa5a4eb81b8b88aeb5d2b6f4c47356fd0a62923Jason Sams#include <GLES/glext.h>
261aa5a4eb81b8b88aeb5d2b6f4c47356fd0a62923Jason Sams
27326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsusing namespace android;
28326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsusing namespace android::renderscript;
29326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
30e57691037aea219562ac686429b4b98202aab7bcJason Sams#define GET_TLS()  Context::ScriptTLSStruct * tls = \
31e57691037aea219562ac686429b4b98202aab7bcJason Sams    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
32e57691037aea219562ac686429b4b98202aab7bcJason Sams    Context * rsc = tls->mContext; \
33e57691037aea219562ac686429b4b98202aab7bcJason Sams    ScriptC * sc = (ScriptC *) tls->mScript
34e57691037aea219562ac686429b4b98202aab7bcJason Sams
35326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
36326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsScriptC::ScriptC()
37326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
381ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    mAccScript = NULL;
39efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    memset(&mProgram, 0, sizeof(mProgram));
40326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
41326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
42326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsScriptC::~ScriptC()
43326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
441ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    if (mAccScript) {
451ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich        accDeleteScript(mAccScript);
461ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    }
47326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
48326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
49326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
50e57691037aea219562ac686429b4b98202aab7bcJason Samsbool ScriptC::run(Context *rsc, uint32_t launchIndex)
51326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
52d34b725ac1752f5a234c7643a0b65245591ea1ccJason Sams    Context::ScriptTLSStruct * tls =
53e57691037aea219562ac686429b4b98202aab7bcJason Sams    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
54a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams
55a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams    if (mEnviroment.mFragmentStore.get()) {
56a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
57a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams    }
58a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams    if (mEnviroment.mFragment.get()) {
59a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams        rsc->setFragment(mEnviroment.mFragment.get());
60a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams    }
618ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    if (mEnviroment.mVertex.get()) {
628ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams        rsc->setVertex(mEnviroment.mVertex.get());
638ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    }
64a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams
659c4e4ca9ff75a7fe18544c83fcf782e46c9b6ac2Joe Onorato    if (launchIndex == 0) {
669c4e4ca9ff75a7fe18544c83fcf782e46c9b6ac2Joe Onorato        mEnviroment.mStartTimeMillis
679c4e4ca9ff75a7fe18544c83fcf782e46c9b6ac2Joe Onorato                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
689c4e4ca9ff75a7fe18544c83fcf782e46c9b6ac2Joe Onorato    }
699c4e4ca9ff75a7fe18544c83fcf782e46c9b6ac2Joe Onorato
701d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
711d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        if (mProgram.mSlotPointers[ct]) {
721d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            *mProgram.mSlotPointers[ct] = mSlots[ct]->getPtr();
731d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        }
741d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    }
751d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams
76e45ac6e91864f2a6617b6a2c0aa87cdb62cf58fdJason Sams    bool ret = false;
77e57691037aea219562ac686429b4b98202aab7bcJason Sams    tls->mScript = this;
78e45ac6e91864f2a6617b6a2c0aa87cdb62cf58fdJason Sams    ret = mProgram.mScript(launchIndex) != 0;
79e57691037aea219562ac686429b4b98202aab7bcJason Sams    tls->mScript = NULL;
80e45ac6e91864f2a6617b6a2c0aa87cdb62cf58fdJason Sams    return ret;
81326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
82326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
83326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsScriptCState::ScriptCState()
84326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
85326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    clear();
86326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
87326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
88326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsScriptCState::~ScriptCState()
89326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
901ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    if (mAccScript) {
911ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich        accDeleteScript(mAccScript);
921ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    }
93326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
94326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
95326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid ScriptCState::clear()
96326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
97efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    memset(&mProgram, 0, sizeof(mProgram));
98efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams
998b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
1008b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams        mConstantBufferTypes[ct].clear();
101fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        mSlotNames[ct].setTo("");
10290b36a88cf0cc549b296ac15a249ea7786c6de9eJason Sams        mSlotWritable[ct] = false;
1038b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams    }
104efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams
105efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    memset(&mEnviroment, 0, sizeof(mEnviroment));
106efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    mEnviroment.mClearColor[0] = 0;
107efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    mEnviroment.mClearColor[1] = 0;
108efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    mEnviroment.mClearColor[2] = 0;
109efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    mEnviroment.mClearColor[3] = 1;
110efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    mEnviroment.mClearDepth = 1;
111efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    mEnviroment.mClearStencil = 0;
112efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    mEnviroment.mIsRoot = false;
113efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams
1141ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    mAccScript = NULL;
115efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams
11657b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    mInt32Defines.clear();
11757b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    mFloatDefines.clear();
1181f52633fefd1862451e6a30209d590680d02beecJason Sams}
1191f52633fefd1862451e6a30209d590680d02beecJason Sams
120d34b725ac1752f5a234c7643a0b65245591ea1ccJason Samsstatic ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name)
12129df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams{
12229df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams    const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
12329df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams    if (sym) {
12429df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams        return sym->mPtr;
12529df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams    }
12629df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams    LOGE("ScriptC sym lookup failed for %s", name);
12729df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams    return NULL;
12829df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams}
129a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams
130a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Samsvoid ScriptCState::runCompiler(Context *rsc)
1311f52633fefd1862451e6a30209d590680d02beecJason Sams{
1321f52633fefd1862451e6a30209d590680d02beecJason Sams    mAccScript = accCreateScript();
133a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams    String8 tmp;
134a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams
135a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams    rsc->appendNameDefines(&tmp);
136f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams    appendDecls(&tmp);
13757b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    rsc->appendVarDefines(&tmp);
13857b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    appendVarDefines(&tmp);
1398b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams    appendTypes(&tmp);
140b5909ce06dd10dcb5ac715572a05b2d225b77c98Jason Sams    tmp.append("#line 1\n");
1411f52633fefd1862451e6a30209d590680d02beecJason Sams
142a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams    const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
143a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams    int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ;
144a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams    accScriptSource(mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
14529df66f82aeef7fa7e2cf00edbf00d43c822b05aJason Sams    accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
1461f52633fefd1862451e6a30209d590680d02beecJason Sams    accCompileScript(mAccScript);
147efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
1481d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    accGetScriptLabel(mAccScript, "init", (ACCvoid**) &mProgram.mInit);
1491030893d9b99b72468034da13df025bda479bb97Jason Sams    rsAssert(mProgram.mScript);
1501030893d9b99b72468034da13df025bda479bb97Jason Sams
151f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams    if (!mProgram.mScript) {
152f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams        ACCchar buf[4096];
153f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams        ACCsizei len;
154f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams        accGetScriptInfoLog(mAccScript, sizeof(buf), &len, buf);
155f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams        LOGE(buf);
156f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams    }
157f1685045e3423f2e342c3d74c206a25d72eba89dJason Sams
1581d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    if (mProgram.mInit) {
1591d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        mProgram.mInit();
1601d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    }
1611d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams
1621d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
1631d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        if (mSlotNames[ct].length() > 0) {
1641d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            accGetScriptLabel(mAccScript,
1651d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                              mSlotNames[ct].string(),
1661d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                              (ACCvoid**) &mProgram.mSlotPointers[ct]);
1671d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            LOGE("var  %s  %p", mSlotNames[ct].string(), mProgram.mSlotPointers[ct]);
1681d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        }
1691d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    }
1701d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams
1718ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
1728ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
1738ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
174a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams
1751030893d9b99b72468034da13df025bda479bb97Jason Sams    if (mProgram.mScript) {
1761030893d9b99b72468034da13df025bda479bb97Jason Sams        const static int pragmaMax = 16;
1771030893d9b99b72468034da13df025bda479bb97Jason Sams        ACCsizei pragmaCount;
1781030893d9b99b72468034da13df025bda479bb97Jason Sams        ACCchar * str[pragmaMax];
1791030893d9b99b72468034da13df025bda479bb97Jason Sams        accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]);
1801030893d9b99b72468034da13df025bda479bb97Jason Sams
1811030893d9b99b72468034da13df025bda479bb97Jason Sams        for (int ct=0; ct < pragmaCount; ct+=2) {
1821030893d9b99b72468034da13df025bda479bb97Jason Sams            if (!strcmp(str[ct], "version")) {
1831030893d9b99b72468034da13df025bda479bb97Jason Sams                continue;
1841030893d9b99b72468034da13df025bda479bb97Jason Sams            }
1851030893d9b99b72468034da13df025bda479bb97Jason Sams
1861030893d9b99b72468034da13df025bda479bb97Jason Sams            if (!strcmp(str[ct], "stateVertex")) {
1878ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                if (!strcmp(str[ct+1], "default")) {
1888ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    continue;
1898ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                }
1908ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                if (!strcmp(str[ct+1], "parent")) {
1918ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    mEnviroment.mVertex.clear();
1928ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    continue;
1938ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                }
1948ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
1958ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                if (pv != NULL) {
1968ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    mEnviroment.mVertex.set(pv);
1978ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    continue;
1988ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                }
1991030893d9b99b72468034da13df025bda479bb97Jason Sams                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
2001030893d9b99b72468034da13df025bda479bb97Jason Sams            }
2011030893d9b99b72468034da13df025bda479bb97Jason Sams
2021030893d9b99b72468034da13df025bda479bb97Jason Sams            if (!strcmp(str[ct], "stateRaster")) {
2031030893d9b99b72468034da13df025bda479bb97Jason Sams                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
2041030893d9b99b72468034da13df025bda479bb97Jason Sams            }
2051030893d9b99b72468034da13df025bda479bb97Jason Sams
2061030893d9b99b72468034da13df025bda479bb97Jason Sams            if (!strcmp(str[ct], "stateFragment")) {
2078ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                if (!strcmp(str[ct+1], "default")) {
2088ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    continue;
2098ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                }
2108ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                if (!strcmp(str[ct+1], "parent")) {
2118ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    mEnviroment.mFragment.clear();
2128ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    continue;
2138ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                }
2148ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
215a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams                if (pf != NULL) {
216a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams                    mEnviroment.mFragment.set(pf);
2171030893d9b99b72468034da13df025bda479bb97Jason Sams                    continue;
2181030893d9b99b72468034da13df025bda479bb97Jason Sams                }
2191030893d9b99b72468034da13df025bda479bb97Jason Sams                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
2201030893d9b99b72468034da13df025bda479bb97Jason Sams            }
2211030893d9b99b72468034da13df025bda479bb97Jason Sams
2221030893d9b99b72468034da13df025bda479bb97Jason Sams            if (!strcmp(str[ct], "stateFragmentStore")) {
2238ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                if (!strcmp(str[ct+1], "default")) {
2248ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    continue;
2258ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                }
2268ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                if (!strcmp(str[ct+1], "parent")) {
2278ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    mEnviroment.mFragmentStore.clear();
2288ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                    continue;
2298ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams                }
230d34b725ac1752f5a234c7643a0b65245591ea1ccJason Sams                ProgramFragmentStore * pfs =
231a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams                    (ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
232a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams                if (pfs != NULL) {
233a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams                    mEnviroment.mFragmentStore.set(pfs);
2341030893d9b99b72468034da13df025bda479bb97Jason Sams                    continue;
2351030893d9b99b72468034da13df025bda479bb97Jason Sams                }
2361030893d9b99b72468034da13df025bda479bb97Jason Sams                LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]);
2371030893d9b99b72468034da13df025bda479bb97Jason Sams            }
2381030893d9b99b72468034da13df025bda479bb97Jason Sams
2391030893d9b99b72468034da13df025bda479bb97Jason Sams        }
2401030893d9b99b72468034da13df025bda479bb97Jason Sams
241d34b725ac1752f5a234c7643a0b65245591ea1ccJason Sams
2421030893d9b99b72468034da13df025bda479bb97Jason Sams    } else {
2431030893d9b99b72468034da13df025bda479bb97Jason Sams        // Deal with an error.
2441030893d9b99b72468034da13df025bda479bb97Jason Sams    }
24557b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato}
2461030893d9b99b72468034da13df025bda479bb97Jason Sams
2471d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Samsstatic void appendElementBody(String8 *s, const Element *e)
2481d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams{
2491d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    s->append(" {\n");
2501d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
2511d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        const Component *c = e->getComponent(ct2);
2521d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        s->append("    ");
2531d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        s->append(c->getCType());
2541d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        s->append(" ");
2551d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        s->append(c->getComponentName());
2561d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        s->append(";\n");
2571d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    }
2581d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    s->append("}");
2591d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams}
26057b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato
26157b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onoratovoid ScriptCState::appendVarDefines(String8 *str)
26257b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato{
26357b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    char buf[256];
26457b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    LOGD("appendVarDefines mInt32Defines.size()=%d mFloatDefines.size()=%d\n",
26557b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato            mInt32Defines.size(), mFloatDefines.size());
26657b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
26757b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append("#define ");
26857b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append(mInt32Defines.keyAt(ct));
26957b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append(" ");
27057b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
27157b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append(buf);
27257b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    }
27357b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
27457b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append("#define ");
27557b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append(mFloatDefines.keyAt(ct));
27657b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append(" ");
27757b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
27857b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato        str->append(buf);
27957b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    }
280326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
281326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
2821d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams
2831d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams
2848b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Samsvoid ScriptCState::appendTypes(String8 *str)
2858b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams{
2868b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams    char buf[256];
287fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams    String8 tmp;
2888b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams
289fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams    for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
2908b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams        const Type *t = mConstantBufferTypes[ct].get();
291fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        if (!t) {
2928b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams            continue;
2938b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams        }
294fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        const Element *e = t->getElement();
2951d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        if (e->getName() && (e->getComponentCount() > 1)) {
2961d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            String8 s("struct struct_");
2971d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append(e->getName());
2981d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            appendElementBody(&s, e);
2991d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append(";\n");
3001d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append("#define ");
3011d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append(e->getName());
3021d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append("_t struct struct_");
3031d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append(e->getName());
3041d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append("\n\n");
3051d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            LOGD(s);
3061d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            str->append(s);
3071d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        }
308fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams
309fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        if (t->getName()) {
310fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
311fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                const Component *c = e->getComponent(ct2);
312fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.setTo("#define OFFSETOF_");
313fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append(t->getName());
314fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append("_");
315fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append(c->getComponentName());
316fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                sprintf(buf, " %i\n", ct2);
317fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append(buf);
3181d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                LOGD(tmp);
319fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                str->append(tmp);
320fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams            }
3218b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams        }
3228b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams
323fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        if (mSlotNames[ct].length() > 0) {
3241d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            String8 s;
3251d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            if (e->getComponentCount() > 1) {
3261d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                if (e->getName()) {
3271d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    // Use the named struct
3281d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.setTo(e->getName());
3291d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.append("_t *");
3301d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                } else {
3311d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    // create an struct named from the slot.
3321d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.setTo("struct ");
3331d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.append(mSlotNames[ct]);
3341d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.append("_s");
3351d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    appendElementBody(&s, e);
3361d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.append(";\n");
3371d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.append("struct ");
3381d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.append(mSlotNames[ct]);
3391d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    s.append("_s * ");
3401d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                }
3411d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            } else {
3421d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                // Just make an array
3431d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                s.setTo(e->getComponent(0)->getCType());
3441d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                s.append("_t *");
3451d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            }
3461d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append(mSlotNames[ct]);
3471d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            s.append(";\n");
3481d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            LOGD(s);
3491d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            str->append(s);
3501d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams#if 0
351fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
352fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                const Component *c = e->getComponent(ct2);
353fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.setTo("#define ");
354fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append(mSlotNames[ct]);
355fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append("_");
356fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append(c->getComponentName());
357fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                switch (c->getType()) {
358fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                case Component::FLOAT:
359fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    tmp.append(" loadF(");
360fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    break;
361fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                case Component::SIGNED:
362fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    sprintf(buf, " loadI%i(", c->getBits());
363fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    tmp.append(buf);
364fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    break;
365fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                case Component::UNSIGNED:
366fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    sprintf(buf, " loadU%i(", c->getBits());
367fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    tmp.append(buf);
368fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                    break;
369fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                }
370fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                sprintf(buf, "%i, %i)\n", ct, ct2);
371fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                tmp.append(buf);
372fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams
3731d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                LOGD(tmp);
374fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams                str->append(tmp);
375fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams            }
3761d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams#endif
377fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        }
3788b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams    }
3798b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams}
3808b2c065dfc16c148e2829a19e83d2269b9bcd4ccJason Sams
38157b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato
382326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace android {
383326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace renderscript {
384326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
385326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_ScriptCBegin(Context * rsc)
386326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
387326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    ScriptCState *ss = &rsc->mScriptC;
388326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    ss->clear();
389326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
390326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
391efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Samsvoid rsi_ScriptCSetScript(Context * rsc, void *vp)
392326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
393326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    ScriptCState *ss = &rsc->mScriptC;
394e45ac6e91864f2a6617b6a2c0aa87cdb62cf58fdJason Sams    ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
395326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
396326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
3971f52633fefd1862451e6a30209d590680d02beecJason Samsvoid rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
3981f52633fefd1862451e6a30209d590680d02beecJason Sams{
3991f52633fefd1862451e6a30209d590680d02beecJason Sams    ScriptCState *ss = &rsc->mScriptC;
400efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    ss->mProgram.mScriptText = text;
401efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    ss->mProgram.mScriptTextLength = len;
4021f52633fefd1862451e6a30209d590680d02beecJason Sams}
4031f52633fefd1862451e6a30209d590680d02beecJason Sams
4041f52633fefd1862451e6a30209d590680d02beecJason Sams
405326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsRsScript rsi_ScriptCCreate(Context * rsc)
406326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
407326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    ScriptCState *ss = &rsc->mScriptC;
408326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
409a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams    ss->runCompiler(rsc);
4101f52633fefd1862451e6a30209d590680d02beecJason Sams
411326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    ScriptC *s = new ScriptC();
4129397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams    s->incUserRef();
4131ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    s->mAccScript = ss->mAccScript;
4141ef8b80bc49f415b93912fe7335f852953bde4a4Jack Palevich    ss->mAccScript = NULL;
415efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    s->mEnviroment = ss->mEnviroment;
416efb8de1ef851c9c2a042ad06f64e33bb8b366041Jason Sams    s->mProgram = ss->mProgram;
417fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
418fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
419fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams        s->mSlotNames[ct] = ss->mSlotNames[ct];
42090b36a88cf0cc549b296ac15a249ea7786c6de9eJason Sams        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
421fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams    }
4221030893d9b99b72468034da13df025bda479bb97Jason Sams
423fa51719e6c1bd17b3f347477b4827face9ab647eJason Sams    ss->clear();
424326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    return s;
425326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
426326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
42757b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onoratovoid rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value)
42857b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato{
42957b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    ScriptCState *ss = &rsc->mScriptC;
43057b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    ss->mFloatDefines.add(String8(name), value);
43157b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato}
43257b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato
43357b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onoratovoid rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value)
43457b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato{
43557b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    ScriptCState *ss = &rsc->mScriptC;
43657b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato    ss->mInt32Defines.add(String8(name), value);
43757b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato}
43857b79ceb1126e3797fa42367b97dd7bcfcda1ed9Joe Onorato
439326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
440326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
441326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
442326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
443