Home | History | Annotate | Download | only in rs
      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 
     32 ThreadIO::ThreadIO() {
     33     mRunning = true;
     34     mPureFifo = false;
     35     mMaxInlineSize = 1024;
     36 }
     37 
     38 ThreadIO::~ThreadIO() {
     39 }
     40 
     41 void ThreadIO::init() {
     42     mToClient.init();
     43     mToCore.init();
     44 }
     45 
     46 void ThreadIO::shutdown() {
     47     mRunning = false;
     48     mToCore.shutdown();
     49 }
     50 
     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 
     62 void ThreadIO::coreCommit() {
     63     mToCore.writeAsync(&mSendBuffer, mSendLen);
     64 }
     65 
     66 void ThreadIO::clientShutdown() {
     67     mToClient.shutdown();
     68 }
     69 
     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 
     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 
     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 
     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 
    100 void ThreadIO::setTimeoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) {
    101     //mToCore.setTimeoutCallback(cb, dat, timeout);
    102 }
    103 
    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 
    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 
    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 
    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