1 /*
2 * Copyright (C) 2009 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 "rsContext.h"
18 #include "rsThreadIO.h"
19 #include "rsgApiStructs.h"
20
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24
25 #include <fcntl.h>
26 #include <poll.h>
27
28
29 using namespace android;
30 using namespace android::renderscript;
31
ThreadIO()32 ThreadIO::ThreadIO() {
33 mRunning = true;
34 mPureFifo = false;
35 mMaxInlineSize = 1024;
36 }
37
~ThreadIO()38 ThreadIO::~ThreadIO() {
39 }
40
init()41 void ThreadIO::init() {
42 mToClient.init();
43 mToCore.init();
44 }
45
shutdown()46 void ThreadIO::shutdown() {
47 mRunning = false;
48 mToCore.shutdown();
49 }
50
coreHeader(uint32_t cmdID,size_t dataLen)51 void * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) {
52 //ALOGE("coreHeader %i %i", cmdID, dataLen);
53 CoreCmdHeader *hdr = (CoreCmdHeader *)&mSendBuffer[0];
54 hdr->bytes = dataLen;
55 hdr->cmdID = cmdID;
56 mSendLen = dataLen + sizeof(CoreCmdHeader);
57 //mToCoreSocket.writeAsync(&hdr, sizeof(hdr));
58 //ALOGE("coreHeader ret ");
59 return &mSendBuffer[sizeof(CoreCmdHeader)];
60 }
61
coreCommit()62 void ThreadIO::coreCommit() {
63 mToCore.writeAsync(&mSendBuffer, mSendLen);
64 }
65
clientShutdown()66 void ThreadIO::clientShutdown() {
67 mToClient.shutdown();
68 }
69
coreWrite(const void * data,size_t len)70 void ThreadIO::coreWrite(const void *data, size_t len) {
71 //ALOGV("core write %p %i", data, (int)len);
72 mToCore.writeAsync(data, len, true);
73 }
74
coreRead(void * data,size_t len)75 void ThreadIO::coreRead(void *data, size_t len) {
76 //ALOGV("core read %p %i", data, (int)len);
77 mToCore.read(data, len);
78 }
79
coreSetReturn(const void * data,size_t dataLen)80 void ThreadIO::coreSetReturn(const void *data, size_t dataLen) {
81 uint32_t buf;
82 if (data == NULL) {
83 data = &buf;
84 dataLen = sizeof(buf);
85 }
86
87 mToCore.readReturn(data, dataLen);
88 }
89
coreGetReturn(void * data,size_t dataLen)90 void ThreadIO::coreGetReturn(void *data, size_t dataLen) {
91 uint32_t buf;
92 if (data == NULL) {
93 data = &buf;
94 dataLen = sizeof(buf);
95 }
96
97 mToCore.writeWaitReturn(data, dataLen);
98 }
99
setTimeoutCallback(void (* cb)(void *),void * dat,uint64_t timeout)100 void ThreadIO::setTimeoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) {
101 //mToCore.setTimeoutCallback(cb, dat, timeout);
102 }
103
playCoreCommands(Context * con,int waitFd)104 bool ThreadIO::playCoreCommands(Context *con, int waitFd) {
105 bool ret = false;
106 const bool isLocal = !isPureFifo();
107
108 uint8_t buf[2 * 1024];
109 const CoreCmdHeader *cmd = (const CoreCmdHeader *)&buf[0];
110 const void * data = (const void *)&buf[sizeof(CoreCmdHeader)];
111
112 struct pollfd p[2];
113 p[0].fd = mToCore.getReadFd();
114 p[0].events = POLLIN;
115 p[0].revents = 0;
116 p[1].fd = waitFd;
117 p[1].events = POLLIN;
118 p[1].revents = 0;
119 int pollCount = 1;
120 if (waitFd >= 0) {
121 pollCount = 2;
122 }
123
124 if (con->props.mLogTimes) {
125 con->timerSet(Context::RS_TIMER_IDLE);
126 }
127
128 int waitTime = -1;
129 while (mRunning) {
130 int pr = poll(p, pollCount, waitTime);
131 if (pr <= 0) {
132 break;
133 }
134
135 if (p[0].revents) {
136 size_t r = 0;
137 if (isLocal) {
138 r = mToCore.read(&buf[0], sizeof(CoreCmdHeader));
139 mToCore.read(&buf[sizeof(CoreCmdHeader)], cmd->bytes);
140 if (r != sizeof(CoreCmdHeader)) {
141 // exception or timeout occurred.
142 break;
143 }
144 } else {
145 r = mToCore.read((void *)&cmd->cmdID, sizeof(cmd->cmdID));
146 }
147
148
149 ret = true;
150 if (con->props.mLogTimes) {
151 con->timerSet(Context::RS_TIMER_INTERNAL);
152 }
153 //ALOGV("playCoreCommands 3 %i %i", cmd->cmdID, cmd->bytes);
154
155 if (cmd->cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) {
156 rsAssert(cmd->cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *)));
157 ALOGE("playCoreCommands error con %p, cmd %i", con, cmd->cmdID);
158 }
159
160 if (isLocal) {
161 gPlaybackFuncs[cmd->cmdID](con, data, cmd->bytes);
162 } else {
163 gPlaybackRemoteFuncs[cmd->cmdID](con, this);
164 }
165
166 if (con->props.mLogTimes) {
167 con->timerSet(Context::RS_TIMER_IDLE);
168 }
169
170 if (waitFd < 0) {
171 // If we don't have a secondary wait object we should stop blocking now
172 // that at least one command has been processed.
173 waitTime = 0;
174 }
175 }
176
177 if (p[1].revents && !p[0].revents) {
178 // We want to finish processing fifo events before processing the vsync.
179 // Otherwise we can end up falling behind and having tremendous lag.
180 break;
181 }
182 }
183 return ret;
184 }
185
getClientHeader(size_t * receiveLen,uint32_t * usrID)186 RsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) {
187 //ALOGE("getClientHeader");
188 mToClient.read(&mLastClientHeader, sizeof(mLastClientHeader));
189
190 receiveLen[0] = mLastClientHeader.bytes;
191 usrID[0] = mLastClientHeader.userID;
192 //ALOGE("getClientHeader %i %i %i", mLastClientHeader.cmdID, usrID[0], receiveLen[0]);
193 return (RsMessageToClientType)mLastClientHeader.cmdID;
194 }
195
getClientPayload(void * data,size_t * receiveLen,uint32_t * usrID,size_t bufferLen)196 RsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen,
197 uint32_t *usrID, size_t bufferLen) {
198 //ALOGE("getClientPayload");
199 receiveLen[0] = mLastClientHeader.bytes;
200 usrID[0] = mLastClientHeader.userID;
201 if (bufferLen < mLastClientHeader.bytes) {
202 return RS_MESSAGE_TO_CLIENT_RESIZE;
203 }
204 if (receiveLen[0]) {
205 mToClient.read(data, receiveLen[0]);
206 }
207 //ALOGE("getClientPayload x");
208 return (RsMessageToClientType)mLastClientHeader.cmdID;
209 }
210
sendToClient(RsMessageToClientType cmdID,uint32_t usrID,const void * data,size_t dataLen,bool waitForSpace)211 bool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data,
212 size_t dataLen, bool waitForSpace) {
213
214 //ALOGE("sendToClient %i %i %i", cmdID, usrID, (int)dataLen);
215 ClientCmdHeader hdr;
216 hdr.bytes = dataLen;
217 hdr.cmdID = cmdID;
218 hdr.userID = usrID;
219
220 mToClient.writeAsync(&hdr, sizeof(hdr));
221 if (dataLen) {
222 mToClient.writeAsync(data, dataLen);
223 }
224
225 //ALOGE("sendToClient x");
226 return true;
227 }
228
229