1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <malloc.h> 18#include <string.h> 19#include <pthread.h> 20 21#include "RenderScript.h" 22#include "rs.h" 23 24using namespace android; 25using namespace RSC; 26 27bool RS::gInitialized = false; 28pthread_mutex_t RS::gInitMutex = PTHREAD_MUTEX_INITIALIZER; 29 30RS::RS() { 31 mDev = NULL; 32 mContext = NULL; 33 mErrorFunc = NULL; 34 mMessageFunc = NULL; 35 mMessageRun = false; 36 37 memset(&mElements, 0, sizeof(mElements)); 38} 39 40RS::~RS() { 41 mMessageRun = false; 42 43 rsContextDeinitToClient(mContext); 44 45 void *res = NULL; 46 int status = pthread_join(mMessageThreadId, &res); 47 48 rsContextDestroy(mContext); 49 mContext = NULL; 50 rsDeviceDestroy(mDev); 51 mDev = NULL; 52} 53 54bool RS::init(bool forceCpu, bool synchronous) { 55 return RS::init(RS_VERSION, forceCpu, synchronous); 56} 57 58bool RS::init(int targetApi, bool forceCpu, bool synchronous) { 59 mDev = rsDeviceCreate(); 60 if (mDev == 0) { 61 ALOGE("Device creation failed"); 62 return false; 63 } 64 65 mContext = rsContextCreate(mDev, 0, targetApi, RS_CONTEXT_TYPE_NORMAL, forceCpu, synchronous); 66 if (mContext == 0) { 67 ALOGE("Context creation failed"); 68 return false; 69 } 70 71 pid_t mNativeMessageThreadId; 72 73 int status = pthread_create(&mMessageThreadId, NULL, threadProc, this); 74 if (status) { 75 ALOGE("Failed to start RS message thread."); 76 return false; 77 } 78 // Wait for the message thread to be active. 79 while (!mMessageRun) { 80 usleep(1000); 81 } 82 83 return true; 84} 85 86void RS::throwError(const char *err) const { 87 ALOGE("RS CPP error: %s", err); 88 int * v = NULL; 89 v[0] = 0; 90} 91 92 93void * RS::threadProc(void *vrsc) { 94 RS *rs = static_cast<RS *>(vrsc); 95 size_t rbuf_size = 256; 96 void * rbuf = malloc(rbuf_size); 97 98 rsContextInitToClient(rs->mContext); 99 rs->mMessageRun = true; 100 101 while (rs->mMessageRun) { 102 size_t receiveLen = 0; 103 uint32_t usrID = 0; 104 uint32_t subID = 0; 105 RsMessageToClientType r = rsContextPeekMessage(rs->mContext, 106 &receiveLen, sizeof(receiveLen), 107 &usrID, sizeof(usrID)); 108 109 if (receiveLen >= rbuf_size) { 110 rbuf_size = receiveLen + 32; 111 rbuf = realloc(rbuf, rbuf_size); 112 } 113 if (!rbuf) { 114 ALOGE("RS::message handler realloc error %zu", rbuf_size); 115 // No clean way to recover now? 116 } 117 rsContextGetMessage(rs->mContext, rbuf, rbuf_size, &receiveLen, sizeof(receiveLen), 118 &subID, sizeof(subID)); 119 120 switch(r) { 121 case RS_MESSAGE_TO_CLIENT_ERROR: 122 ALOGE("RS Error %s", (const char *)rbuf); 123 124 if(rs->mMessageFunc != NULL) { 125 rs->mErrorFunc(usrID, (const char *)rbuf); 126 } 127 break; 128 case RS_MESSAGE_TO_CLIENT_NONE: 129 case RS_MESSAGE_TO_CLIENT_EXCEPTION: 130 case RS_MESSAGE_TO_CLIENT_RESIZE: 131 // teardown. But we want to avoid starving other threads during 132 // teardown by yielding until the next line in the destructor can 133 // execute to set mRun = false. Note that the FIFO sends an 134 // empty NONE message when it reaches its destructor. 135 usleep(1000); 136 break; 137 case RS_MESSAGE_TO_CLIENT_USER: 138 if(rs->mMessageFunc != NULL) { 139 rs->mMessageFunc(usrID, rbuf, receiveLen); 140 } else { 141 ALOGE("Received a message from the script with no message handler installed."); 142 } 143 break; 144 145 default: 146 ALOGE("RS unknown message type %i", r); 147 } 148 } 149 150 if (rbuf) { 151 free(rbuf); 152 } 153 ALOGE("RS Message thread exiting."); 154 return NULL; 155} 156 157void RS::setErrorHandler(ErrorHandlerFunc_t func) { 158 mErrorFunc = func; 159} 160 161void RS::setMessageHandler(MessageHandlerFunc_t func) { 162 mMessageFunc = func; 163} 164 165void RS::finish() { 166 rsContextFinish(mContext); 167} 168