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