• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2011 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 "rs.h"
18  #include "rsDevice.h"
19  #include "rsContext.h"
20  #include "rsThreadIO.h"
21  
22  #ifndef RS_COMPATIBILITY_LIB
23  #include "rsMesh.h"
24  #include <ui/FramebufferNativeWindow.h>
25  #include <gui/DisplayEventReceiver.h>
26  #endif
27  
28  #include <sys/types.h>
29  #include <sys/resource.h>
30  #include <sched.h>
31  
32  #include <sys/syscall.h>
33  #include <string.h>
34  #include <dlfcn.h>
35  
36  #ifndef RS_SERVER
37  #include <cutils/properties.h>
38  #endif
39  
40  #ifdef RS_SERVER
41  // Android exposes gettid(), standard Linux does not
gettid()42  static pid_t gettid() {
43      return syscall(SYS_gettid);
44  }
45  #endif
46  
47  using namespace android;
48  using namespace android::renderscript;
49  
50  pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
51  pthread_mutex_t Context::gMessageMutex = PTHREAD_MUTEX_INITIALIZER;
52  pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
53  
initGLThread()54  bool Context::initGLThread() {
55      pthread_mutex_lock(&gInitMutex);
56  
57      if (!mHal.funcs.initGraphics(this)) {
58          pthread_mutex_unlock(&gInitMutex);
59          ALOGE("%p initGraphics failed", this);
60          return false;
61      }
62  
63      pthread_mutex_unlock(&gInitMutex);
64      return true;
65  }
66  
deinitEGL()67  void Context::deinitEGL() {
68  #ifndef RS_COMPATIBILITY_LIB
69      mHal.funcs.shutdownGraphics(this);
70  #endif
71  }
72  
PushState(Context * con)73  Context::PushState::PushState(Context *con) {
74      mRsc = con;
75  #ifndef RS_COMPATIBILITY_LIB
76      if (con->mIsGraphicsContext) {
77          mFragment.set(con->getProgramFragment());
78          mVertex.set(con->getProgramVertex());
79          mStore.set(con->getProgramStore());
80          mRaster.set(con->getProgramRaster());
81          mFont.set(con->getFont());
82      }
83  #endif
84  }
85  
~PushState()86  Context::PushState::~PushState() {
87  #ifndef RS_COMPATIBILITY_LIB
88      if (mRsc->mIsGraphicsContext) {
89          mRsc->setProgramFragment(mFragment.get());
90          mRsc->setProgramVertex(mVertex.get());
91          mRsc->setProgramStore(mStore.get());
92          mRsc->setProgramRaster(mRaster.get());
93          mRsc->setFont(mFont.get());
94      }
95  #endif
96  }
97  
98  
runScript(Script * s)99  uint32_t Context::runScript(Script *s) {
100      PushState ps(this);
101  
102      uint32_t ret = s->run(this);
103      return ret;
104  }
105  
runRootScript()106  uint32_t Context::runRootScript() {
107      timerSet(RS_TIMER_SCRIPT);
108  #ifndef RS_COMPATIBILITY_LIB
109      mStateFragmentStore.mLast.clear();
110  #endif
111      watchdog.inRoot = true;
112      uint32_t ret = runScript(mRootScript.get());
113      watchdog.inRoot = false;
114  
115      return ret;
116  }
117  
getTime() const118  uint64_t Context::getTime() const {
119  #ifndef ANDROID_RS_SERIALIZE
120      struct timespec t;
121      clock_gettime(CLOCK_MONOTONIC, &t);
122      return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
123  #else
124      return 0;
125  #endif //ANDROID_RS_SERIALIZE
126  }
127  
timerReset()128  void Context::timerReset() {
129      for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
130          mTimers[ct] = 0;
131      }
132  }
133  
timerInit()134  void Context::timerInit() {
135      mTimeLast = getTime();
136      mTimeFrame = mTimeLast;
137      mTimeLastFrame = mTimeLast;
138      mTimerActive = RS_TIMER_INTERNAL;
139      mAverageFPSFrameCount = 0;
140      mAverageFPSStartTime = mTimeLast;
141      mAverageFPS = 0;
142      timerReset();
143  }
144  
timerFrame()145  void Context::timerFrame() {
146      mTimeLastFrame = mTimeFrame;
147      mTimeFrame = getTime();
148      // Update average fps
149      const uint64_t averageFramerateInterval = 1000 * 1000000;
150      mAverageFPSFrameCount ++;
151      uint64_t inverval = mTimeFrame - mAverageFPSStartTime;
152      if (inverval >= averageFramerateInterval) {
153          inverval = inverval / 1000000;
154          mAverageFPS = (mAverageFPSFrameCount * 1000) / inverval;
155          mAverageFPSFrameCount = 0;
156          mAverageFPSStartTime = mTimeFrame;
157      }
158  }
159  
timerSet(Timers tm)160  void Context::timerSet(Timers tm) {
161      uint64_t last = mTimeLast;
162      mTimeLast = getTime();
163      mTimers[mTimerActive] += mTimeLast - last;
164      mTimerActive = tm;
165  }
166  
timerPrint()167  void Context::timerPrint() {
168      double total = 0;
169      for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
170          total += mTimers[ct];
171      }
172      uint64_t frame = mTimeFrame - mTimeLastFrame;
173      mTimeMSLastFrame = frame / 1000000;
174      mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000;
175      mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000;
176  
177  
178      if (props.mLogTimes) {
179          ALOGV("RS: Frame (%i),   Script %2.1f%% (%i),  Swap %2.1f%% (%i),  Idle %2.1f%% (%lli),  Internal %2.1f%% (%lli), Avg fps: %u",
180               mTimeMSLastFrame,
181               100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript,
182               100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap,
183               100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
184               100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
185               mAverageFPS);
186      }
187  }
188  
setupCheck()189  bool Context::setupCheck() {
190  #ifndef RS_COMPATIBILITY_LIB
191      mFragmentStore->setup(this, &mStateFragmentStore);
192      mFragment->setup(this, &mStateFragment);
193      mRaster->setup(this, &mStateRaster);
194      mVertex->setup(this, &mStateVertex);
195      mFBOCache.setup(this);
196  #endif
197      return true;
198  }
199  
200  #ifndef RS_COMPATIBILITY_LIB
setupProgramStore()201  void Context::setupProgramStore() {
202      mFragmentStore->setup(this, &mStateFragmentStore);
203  }
204  #endif
205  
getProp(const char * str)206  static uint32_t getProp(const char *str) {
207  #ifndef RS_SERVER
208      char buf[PROPERTY_VALUE_MAX];
209      property_get(str, buf, "0");
210      return atoi(buf);
211  #else
212      return 0;
213  #endif
214  }
215  
displayDebugStats()216  void Context::displayDebugStats() {
217  #ifndef RS_COMPATIBILITY_LIB
218      char buffer[128];
219      sprintf(buffer, "Avg fps %u, Frame %i ms, Script %i ms", mAverageFPS, mTimeMSLastFrame, mTimeMSLastScript);
220      float oldR, oldG, oldB, oldA;
221      mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA);
222      uint32_t bufferLen = strlen(buffer);
223  
224      ObjectBaseRef<Font> lastFont(getFont());
225      setFont(NULL);
226      float shadowCol = 0.1f;
227      mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f);
228      mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6);
229  
230      mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f);
231      mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7);
232  
233      setFont(lastFont.get());
234      mStateFont.setFontColor(oldR, oldG, oldB, oldA);
235  #endif
236  }
237  
loadRuntime(const char * filename,Context * rsc)238  bool Context::loadRuntime(const char* filename, Context* rsc) {
239  
240      // TODO: store the driverSO somewhere so we can dlclose later
241      void *driverSO = NULL;
242  
243      driverSO = dlopen(filename, RTLD_LAZY);
244      if (driverSO == NULL) {
245          ALOGE("Failed loading RS driver: %s", dlerror());
246          return false;
247      }
248  
249      // Need to call dlerror() to clear buffer before using it for dlsym().
250      (void) dlerror();
251      typedef bool (*HalSig)(Context*, uint32_t, uint32_t);
252      HalSig halInit = (HalSig) dlsym(driverSO, "rsdHalInit");
253  
254      // If we can't find the C variant, we go looking for the C++ version.
255      if (halInit == NULL) {
256          ALOGW("Falling back to find C++ rsdHalInit: %s", dlerror());
257          halInit = (HalSig) dlsym(driverSO,
258                  "_Z10rsdHalInitPN7android12renderscript7ContextEjj");
259      }
260  
261      if (halInit == NULL) {
262          dlclose(driverSO);
263          ALOGE("Failed to find rsdHalInit: %s", dlerror());
264          return false;
265      }
266  
267      if (!(*halInit)(rsc, 0, 0)) {
268          dlclose(driverSO);
269          ALOGE("Hal init failed");
270          return false;
271      }
272  
273      //validate HAL struct
274  
275  
276      return true;
277  }
278  
279  extern "C" bool rsdHalInit(RsContext c, uint32_t version_major, uint32_t version_minor);
280  
threadProc(void * vrsc)281  void * Context::threadProc(void *vrsc) {
282      Context *rsc = static_cast<Context *>(vrsc);
283  #ifndef ANDROID_RS_SERIALIZE
284      rsc->mNativeThreadId = gettid();
285  #ifndef RS_COMPATIBILITY_LIB
286      if (!rsc->isSynchronous()) {
287          setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY);
288      }
289      rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY;
290  #else
291      if (!rsc->isSynchronous()) {
292          setpriority(PRIO_PROCESS, rsc->mNativeThreadId, -4);
293      }
294      rsc->mThreadPriority = -4;
295  #endif
296  #endif //ANDROID_RS_SERIALIZE
297      rsc->props.mLogTimes = getProp("debug.rs.profile") != 0;
298      rsc->props.mLogScripts = getProp("debug.rs.script") != 0;
299      rsc->props.mLogObjects = getProp("debug.rs.object") != 0;
300      rsc->props.mLogShaders = getProp("debug.rs.shader") != 0;
301      rsc->props.mLogShadersAttr = getProp("debug.rs.shader.attributes") != 0;
302      rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms") != 0;
303      rsc->props.mLogVisual = getProp("debug.rs.visual") != 0;
304      rsc->props.mDebugMaxThreads = getProp("debug.rs.max-threads");
305  
306      bool loadDefault = true;
307  
308      // Provide a mechanism for dropping in a different RS driver.
309  #ifndef RS_COMPATIBILITY_LIB
310  #ifdef OVERRIDE_RS_DRIVER
311  #define XSTR(S) #S
312  #define STR(S) XSTR(S)
313  #define OVERRIDE_RS_DRIVER_STRING STR(OVERRIDE_RS_DRIVER)
314  
315      if (getProp("debug.rs.default-CPU-driver") != 0) {
316          ALOGE("Skipping override driver and loading default CPU driver");
317      } else if (rsc->mForceCpu) {
318          ALOGV("Application requested CPU execution");
319      } else if (rsc->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
320          ALOGV("Application requested debug context");
321      } else {
322          if (loadRuntime(OVERRIDE_RS_DRIVER_STRING, rsc)) {
323              ALOGE("Successfully loaded runtime: %s", OVERRIDE_RS_DRIVER_STRING);
324              loadDefault = false;
325          } else {
326              ALOGE("Failed to load runtime %s, loading default", OVERRIDE_RS_DRIVER_STRING);
327          }
328      }
329  
330  #undef XSTR
331  #undef STR
332  #endif  // OVERRIDE_RS_DRIVER
333  
334      if (loadDefault) {
335          if (!loadRuntime("libRSDriver.so", rsc)) {
336              ALOGE("Failed to load default runtime!");
337              rsc->setError(RS_ERROR_FATAL_DRIVER, "Failed loading RS driver");
338              return NULL;
339          }
340      }
341  #else // RS_COMPATIBILITY_LIB
342      if (rsdHalInit(rsc, 0, 0) != true) {
343          return NULL;
344      }
345  #endif
346  
347  
348      rsc->mHal.funcs.setPriority(rsc, rsc->mThreadPriority);
349  
350  #ifndef RS_COMPATIBILITY_LIB
351      if (rsc->mIsGraphicsContext) {
352          if (!rsc->initGLThread()) {
353              rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL");
354              return NULL;
355          }
356  
357          rsc->mStateRaster.init(rsc);
358          rsc->setProgramRaster(NULL);
359          rsc->mStateVertex.init(rsc);
360          rsc->setProgramVertex(NULL);
361          rsc->mStateFragment.init(rsc);
362          rsc->setProgramFragment(NULL);
363          rsc->mStateFragmentStore.init(rsc);
364          rsc->setProgramStore(NULL);
365          rsc->mStateFont.init(rsc);
366          rsc->setFont(NULL);
367          rsc->mStateSampler.init(rsc);
368          rsc->mFBOCache.init(rsc);
369      }
370  #endif
371  
372      rsc->mRunning = true;
373  
374      if (rsc->isSynchronous()) {
375          return NULL;
376      }
377  
378      if (!rsc->mIsGraphicsContext) {
379          while (!rsc->mExit) {
380              rsc->mIO.playCoreCommands(rsc, -1);
381          }
382  #ifndef RS_COMPATIBILITY_LIB
383      } else {
384  #ifndef ANDROID_RS_SERIALIZE
385          DisplayEventReceiver displayEvent;
386          DisplayEventReceiver::Event eventBuffer[1];
387  #endif
388          int vsyncRate = 0;
389          int targetRate = 0;
390  
391          bool drawOnce = false;
392          while (!rsc->mExit) {
393              rsc->timerSet(RS_TIMER_IDLE);
394  
395  #ifndef ANDROID_RS_SERIALIZE
396              if (!rsc->mRootScript.get() || !rsc->mHasSurface || rsc->mPaused) {
397                  targetRate = 0;
398              }
399  
400              if (vsyncRate != targetRate) {
401                  displayEvent.setVsyncRate(targetRate);
402                  vsyncRate = targetRate;
403              }
404              if (targetRate) {
405                  drawOnce |= rsc->mIO.playCoreCommands(rsc, displayEvent.getFd());
406                  while (displayEvent.getEvents(eventBuffer, 1) != 0) {
407                      //ALOGE("vs2 time past %lld", (rsc->getTime() - eventBuffer[0].header.timestamp) / 1000000);
408                  }
409              } else
410  #endif
411              {
412                  drawOnce |= rsc->mIO.playCoreCommands(rsc, -1);
413              }
414  
415              if ((rsc->mRootScript.get() != NULL) && rsc->mHasSurface &&
416                  (targetRate || drawOnce) && !rsc->mPaused) {
417  
418                  drawOnce = false;
419                  targetRate = ((rsc->runRootScript() + 15) / 16);
420  
421                  if (rsc->props.mLogVisual) {
422                      rsc->displayDebugStats();
423                  }
424  
425                  rsc->timerSet(RS_TIMER_CLEAR_SWAP);
426                  rsc->mHal.funcs.swap(rsc);
427                  rsc->timerFrame();
428                  rsc->timerSet(RS_TIMER_INTERNAL);
429                  rsc->timerPrint();
430                  rsc->timerReset();
431              }
432          }
433  #endif
434      }
435  
436      //ALOGV("%p RS Thread exiting", rsc);
437  
438  #ifndef RS_COMPATIBILITY_LIB
439      if (rsc->mIsGraphicsContext) {
440          pthread_mutex_lock(&gInitMutex);
441          rsc->deinitEGL();
442          pthread_mutex_unlock(&gInitMutex);
443      }
444  #endif
445  
446      //ALOGV("%p RS Thread exited", rsc);
447      return NULL;
448  }
449  
destroyWorkerThreadResources()450  void Context::destroyWorkerThreadResources() {
451      //ALOGV("destroyWorkerThreadResources 1");
452      ObjectBase::zeroAllUserRef(this);
453  #ifndef RS_COMPATIBILITY_LIB
454      if (mIsGraphicsContext) {
455           mRaster.clear();
456           mFragment.clear();
457           mVertex.clear();
458           mFragmentStore.clear();
459           mFont.clear();
460           mRootScript.clear();
461           mStateRaster.deinit(this);
462           mStateVertex.deinit(this);
463           mStateFragment.deinit(this);
464           mStateFragmentStore.deinit(this);
465           mStateFont.deinit(this);
466           mStateSampler.deinit(this);
467           mFBOCache.deinit(this);
468      }
469  #endif
470      ObjectBase::freeAllChildren(this);
471      mExit = true;
472      //ALOGV("destroyWorkerThreadResources 2");
473  }
474  
printWatchdogInfo(void * ctx)475  void Context::printWatchdogInfo(void *ctx) {
476      Context *rsc = (Context *)ctx;
477      if (rsc->watchdog.command && rsc->watchdog.file) {
478          ALOGE("RS watchdog timeout: %i  %s  line %i %s", rsc->watchdog.inRoot,
479               rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file);
480      } else {
481          ALOGE("RS watchdog timeout: %i", rsc->watchdog.inRoot);
482      }
483  }
484  
485  
setPriority(int32_t p)486  void Context::setPriority(int32_t p) {
487      // Note: If we put this in the proper "background" policy
488      // the wallpapers can become completly unresponsive at times.
489      // This is probably not what we want for something the user is actively
490      // looking at.
491      mThreadPriority = p;
492      setpriority(PRIO_PROCESS, mNativeThreadId, p);
493      mHal.funcs.setPriority(this, mThreadPriority);
494  }
495  
Context()496  Context::Context() {
497      mDev = NULL;
498      mRunning = false;
499      mExit = false;
500      mPaused = false;
501      mObjHead = NULL;
502      mError = RS_ERROR_NONE;
503      mTargetSdkVersion = 14;
504      mDPI = 96;
505      mIsContextLite = false;
506      memset(&watchdog, 0, sizeof(watchdog));
507      mForceCpu = false;
508      mContextType = RS_CONTEXT_TYPE_NORMAL;
509      mSynchronous = false;
510  }
511  
createContext(Device * dev,const RsSurfaceConfig * sc,RsContextType ct,bool forceCpu,bool synchronous)512  Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc,
513                                   RsContextType ct, bool forceCpu,
514                                   bool synchronous) {
515      Context * rsc = new Context();
516  
517      rsc->mForceCpu = forceCpu;
518      rsc->mSynchronous = synchronous;
519      rsc->mContextType = ct;
520  
521      if (!rsc->initContext(dev, sc)) {
522          delete rsc;
523          return NULL;
524      }
525      return rsc;
526  }
527  
createContextLite()528  Context * Context::createContextLite() {
529      Context * rsc = new Context();
530      rsc->mIsContextLite = true;
531      return rsc;
532  }
533  
initContext(Device * dev,const RsSurfaceConfig * sc)534  bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
535      pthread_mutex_lock(&gInitMutex);
536  
537      mIO.init();
538      mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9);
539  
540      dev->addContext(this);
541      mDev = dev;
542      if (sc) {
543          mUserSurfaceConfig = *sc;
544      } else {
545          memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
546      }
547  
548      mIsGraphicsContext = sc != NULL;
549  
550      int status;
551      pthread_attr_t threadAttr;
552  
553      pthread_mutex_unlock(&gInitMutex);
554  
555      // Global init done at this point.
556  
557      status = pthread_attr_init(&threadAttr);
558      if (status) {
559          ALOGE("Failed to init thread attribute.");
560          return false;
561      }
562  
563      mHasSurface = false;
564  
565      timerInit();
566      timerSet(RS_TIMER_INTERNAL);
567      if (mSynchronous) {
568          threadProc(this);
569      } else {
570          status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
571          if (status) {
572              ALOGE("Failed to start rs context thread.");
573              return false;
574          }
575          while (!mRunning && (mError == RS_ERROR_NONE)) {
576              usleep(100);
577          }
578  
579          if (mError != RS_ERROR_NONE) {
580              ALOGE("Errors during thread init");
581              return false;
582          }
583  
584          pthread_attr_destroy(&threadAttr);
585      }
586      return true;
587  }
588  
~Context()589  Context::~Context() {
590      //ALOGV("%p Context::~Context", this);
591  
592      if (!mIsContextLite) {
593          mPaused = false;
594          void *res;
595  
596          mIO.shutdown();
597          int status = pthread_join(mThreadId, &res);
598          rsAssert(mExit);
599  
600          if (mHal.funcs.shutdownDriver) {
601              mHal.funcs.shutdownDriver(this);
602          }
603  
604          // Global structure cleanup.
605          pthread_mutex_lock(&gInitMutex);
606          if (mDev) {
607              mDev->removeContext(this);
608              mDev = NULL;
609          }
610          pthread_mutex_unlock(&gInitMutex);
611      }
612      //ALOGV("%p Context::~Context done", this);
613  }
614  
615  #ifndef RS_COMPATIBILITY_LIB
setSurface(uint32_t w,uint32_t h,RsNativeWindow sur)616  void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
617      rsAssert(mIsGraphicsContext);
618      mHal.funcs.setSurface(this, w, h, sur);
619  
620      mHasSurface = sur != NULL;
621      mWidth = w;
622      mHeight = h;
623  
624      if (mWidth && mHeight) {
625          mStateVertex.updateSize(this);
626          mFBOCache.updateSize();
627      }
628  }
629  
getCurrentSurfaceWidth() const630  uint32_t Context::getCurrentSurfaceWidth() const {
631      for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
632          if (mFBOCache.mHal.state.colorTargets[i] != NULL) {
633              return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX();
634          }
635      }
636      if (mFBOCache.mHal.state.depthTarget != NULL) {
637          return mFBOCache.mHal.state.depthTarget->getType()->getDimX();
638      }
639      return mWidth;
640  }
641  
getCurrentSurfaceHeight() const642  uint32_t Context::getCurrentSurfaceHeight() const {
643      for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
644          if (mFBOCache.mHal.state.colorTargets[i] != NULL) {
645              return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY();
646          }
647      }
648      if (mFBOCache.mHal.state.depthTarget != NULL) {
649          return mFBOCache.mHal.state.depthTarget->getType()->getDimY();
650      }
651      return mHeight;
652  }
653  
pause()654  void Context::pause() {
655      rsAssert(mIsGraphicsContext);
656      mPaused = true;
657  }
658  
resume()659  void Context::resume() {
660      rsAssert(mIsGraphicsContext);
661      mPaused = false;
662  }
663  
setRootScript(Script * s)664  void Context::setRootScript(Script *s) {
665      rsAssert(mIsGraphicsContext);
666      mRootScript.set(s);
667  }
668  
setProgramStore(ProgramStore * pfs)669  void Context::setProgramStore(ProgramStore *pfs) {
670      rsAssert(mIsGraphicsContext);
671      if (pfs == NULL) {
672          mFragmentStore.set(mStateFragmentStore.mDefault);
673      } else {
674          mFragmentStore.set(pfs);
675      }
676  }
677  
setProgramFragment(ProgramFragment * pf)678  void Context::setProgramFragment(ProgramFragment *pf) {
679      rsAssert(mIsGraphicsContext);
680      if (pf == NULL) {
681          mFragment.set(mStateFragment.mDefault);
682      } else {
683          mFragment.set(pf);
684      }
685  }
686  
setProgramRaster(ProgramRaster * pr)687  void Context::setProgramRaster(ProgramRaster *pr) {
688      rsAssert(mIsGraphicsContext);
689      if (pr == NULL) {
690          mRaster.set(mStateRaster.mDefault);
691      } else {
692          mRaster.set(pr);
693      }
694  }
695  
setProgramVertex(ProgramVertex * pv)696  void Context::setProgramVertex(ProgramVertex *pv) {
697      rsAssert(mIsGraphicsContext);
698      if (pv == NULL) {
699          mVertex.set(mStateVertex.mDefault);
700      } else {
701          mVertex.set(pv);
702      }
703  }
704  
setFont(Font * f)705  void Context::setFont(Font *f) {
706      rsAssert(mIsGraphicsContext);
707      if (f == NULL) {
708          mFont.set(mStateFont.mDefault);
709      } else {
710          mFont.set(f);
711      }
712  }
713  #endif
714  
assignName(ObjectBase * obj,const char * name,uint32_t len)715  void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) {
716      rsAssert(!obj->getName());
717      obj->setName(name, len);
718      mNames.add(obj);
719  }
720  
removeName(ObjectBase * obj)721  void Context::removeName(ObjectBase *obj) {
722      for (size_t ct=0; ct < mNames.size(); ct++) {
723          if (obj == mNames[ct]) {
724              mNames.removeAt(ct);
725              return;
726          }
727      }
728  }
729  
peekMessageToClient(size_t * receiveLen,uint32_t * subID)730  RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) {
731      return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID);
732  }
733  
getMessageToClient(void * data,size_t * receiveLen,uint32_t * subID,size_t bufferLen)734  RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) {
735      return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen);
736  }
737  
sendMessageToClient(const void * data,RsMessageToClientType cmdID,uint32_t subID,size_t len,bool waitForSpace) const738  bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
739                                    uint32_t subID, size_t len, bool waitForSpace) const {
740  
741      pthread_mutex_lock(&gMessageMutex);
742      bool ret = mIO.sendToClient(cmdID, subID, data, len, waitForSpace);
743      pthread_mutex_unlock(&gMessageMutex);
744      return ret;
745  }
746  
initToClient()747  void Context::initToClient() {
748      while (!mRunning) {
749          usleep(100);
750      }
751  }
752  
deinitToClient()753  void Context::deinitToClient() {
754      mIO.clientShutdown();
755  }
756  
setError(RsError e,const char * msg) const757  void Context::setError(RsError e, const char *msg) const {
758      mError = e;
759      sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true);
760  }
761  
762  
dumpDebug() const763  void Context::dumpDebug() const {
764      ALOGE("RS Context debug %p", this);
765      ALOGE("RS Context debug");
766  
767      ALOGE(" RS width %i, height %i", mWidth, mHeight);
768      ALOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
769      ALOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId);
770  }
771  
772  ///////////////////////////////////////////////////////////////////////////////////////////
773  //
774  
775  namespace android {
776  namespace renderscript {
777  
rsi_ContextFinish(Context * rsc)778  void rsi_ContextFinish(Context *rsc) {
779  }
780  
rsi_ContextBindRootScript(Context * rsc,RsScript vs)781  void rsi_ContextBindRootScript(Context *rsc, RsScript vs) {
782  #ifndef RS_COMPATIBILITY_LIB
783      Script *s = static_cast<Script *>(vs);
784      rsc->setRootScript(s);
785  #endif
786  }
787  
rsi_ContextBindSampler(Context * rsc,uint32_t slot,RsSampler vs)788  void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) {
789      Sampler *s = static_cast<Sampler *>(vs);
790  
791      if (slot > RS_MAX_SAMPLER_SLOT) {
792          ALOGE("Invalid sampler slot");
793          return;
794      }
795  
796      s->bindToContext(&rsc->mStateSampler, slot);
797  }
798  
799  #ifndef RS_COMPATIBILITY_LIB
rsi_ContextBindProgramStore(Context * rsc,RsProgramStore vpfs)800  void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) {
801      ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
802      rsc->setProgramStore(pfs);
803  }
804  
rsi_ContextBindProgramFragment(Context * rsc,RsProgramFragment vpf)805  void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) {
806      ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
807      rsc->setProgramFragment(pf);
808  }
809  
rsi_ContextBindProgramRaster(Context * rsc,RsProgramRaster vpr)810  void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) {
811      ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
812      rsc->setProgramRaster(pr);
813  }
814  
rsi_ContextBindProgramVertex(Context * rsc,RsProgramVertex vpv)815  void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) {
816      ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
817      rsc->setProgramVertex(pv);
818  }
819  
rsi_ContextBindFont(Context * rsc,RsFont vfont)820  void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
821      Font *font = static_cast<Font *>(vfont);
822      rsc->setFont(font);
823  }
824  #endif
825  
rsi_AssignName(Context * rsc,RsObjectBase obj,const char * name,size_t name_length)826  void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) {
827      ObjectBase *ob = static_cast<ObjectBase *>(obj);
828      rsc->assignName(ob, name, name_length);
829  }
830  
rsi_ObjDestroy(Context * rsc,void * optr)831  void rsi_ObjDestroy(Context *rsc, void *optr) {
832      ObjectBase *ob = static_cast<ObjectBase *>(optr);
833      rsc->removeName(ob);
834      ob->decUserRef();
835  }
836  
837  #ifndef RS_COMPATIBILITY_LIB
rsi_ContextPause(Context * rsc)838  void rsi_ContextPause(Context *rsc) {
839      rsc->pause();
840  }
841  
rsi_ContextResume(Context * rsc)842  void rsi_ContextResume(Context *rsc) {
843      rsc->resume();
844  }
845  
rsi_ContextSetSurface(Context * rsc,uint32_t w,uint32_t h,RsNativeWindow sur)846  void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
847      rsc->setSurface(w, h, sur);
848  }
849  #endif
850  
rsi_ContextSetPriority(Context * rsc,int32_t p)851  void rsi_ContextSetPriority(Context *rsc, int32_t p) {
852      rsc->setPriority(p);
853  }
854  
rsi_ContextDump(Context * rsc,int32_t bits)855  void rsi_ContextDump(Context *rsc, int32_t bits) {
856      ObjectBase::dumpAll(rsc);
857  }
858  
rsi_ContextDestroyWorker(Context * rsc)859  void rsi_ContextDestroyWorker(Context *rsc) {
860      rsc->destroyWorkerThreadResources();
861  }
862  
rsi_ContextDestroy(Context * rsc)863  void rsi_ContextDestroy(Context *rsc) {
864      //ALOGV("%p rsContextDestroy", rsc);
865      rsContextDestroyWorker(rsc);
866      delete rsc;
867      //ALOGV("%p rsContextDestroy done", rsc);
868  }
869  
870  
rsi_ContextPeekMessage(Context * rsc,size_t * receiveLen,size_t receiveLen_length,uint32_t * subID,size_t subID_length)871  RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
872                                             size_t * receiveLen, size_t receiveLen_length,
873                                             uint32_t * subID, size_t subID_length) {
874      return rsc->peekMessageToClient(receiveLen, subID);
875  }
876  
rsi_ContextGetMessage(Context * rsc,void * data,size_t data_length,size_t * receiveLen,size_t receiveLen_length,uint32_t * subID,size_t subID_length)877  RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
878                                            size_t * receiveLen, size_t receiveLen_length,
879                                            uint32_t * subID, size_t subID_length) {
880      rsAssert(subID_length == sizeof(uint32_t));
881      rsAssert(receiveLen_length == sizeof(size_t));
882      return rsc->getMessageToClient(data, receiveLen, subID, data_length);
883  }
884  
rsi_ContextInitToClient(Context * rsc)885  void rsi_ContextInitToClient(Context *rsc) {
886      rsc->initToClient();
887  }
888  
rsi_ContextDeinitToClient(Context * rsc)889  void rsi_ContextDeinitToClient(Context *rsc) {
890      rsc->deinitToClient();
891  }
892  
rsi_ContextSendMessage(Context * rsc,uint32_t id,const uint8_t * data,size_t len)893  void rsi_ContextSendMessage(Context *rsc, uint32_t id, const uint8_t *data, size_t len) {
894      rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, id, len, true);
895  }
896  
897  }
898  }
899  
rsContextCreate(RsDevice vdev,uint32_t version,uint32_t sdkVersion,RsContextType ct,bool forceCpu,bool synchronous)900  RsContext rsContextCreate(RsDevice vdev, uint32_t version, uint32_t sdkVersion,
901                            RsContextType ct, bool forceCpu, bool synchronous) {
902      //ALOGV("rsContextCreate dev=%p", vdev);
903      Device * dev = static_cast<Device *>(vdev);
904      Context *rsc = Context::createContext(dev, NULL, ct, forceCpu, synchronous);
905      if (rsc) {
906          rsc->setTargetSdkVersion(sdkVersion);
907      }
908      return rsc;
909  }
910  
911  #ifndef RS_COMPATIBILITY_LIB
rsContextCreateGL(RsDevice vdev,uint32_t version,uint32_t sdkVersion,RsSurfaceConfig sc,uint32_t dpi)912  RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
913                              uint32_t sdkVersion, RsSurfaceConfig sc,
914                              uint32_t dpi) {
915      //ALOGV("rsContextCreateGL dev=%p", vdev);
916      Device * dev = static_cast<Device *>(vdev);
917      Context *rsc = Context::createContext(dev, &sc);
918      if (rsc) {
919          rsc->setTargetSdkVersion(sdkVersion);
920          rsc->setDPI(dpi);
921      }
922      //ALOGV("%p rsContextCreateGL ret", rsc);
923      return rsc;
924  }
925  #endif
926  
927  // Only to be called at a3d load time, before object is visible to user
928  // not thread safe
rsaGetName(RsContext con,void * obj,const char ** name)929  void rsaGetName(RsContext con, void * obj, const char **name) {
930      ObjectBase *ob = static_cast<ObjectBase *>(obj);
931      (*name) = ob->getName();
932  }
933