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