• 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  #include "rsgApiStructs.h"
23  
24  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
25  #include "rsMesh.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  #include <inttypes.h>
36  #include <unistd.h>
37  
38  #ifdef RS_COMPATIBILITY_LIB
39  #include "rsCompatibilityLib.h"
40  #endif
41  
42  namespace android {
43  namespace renderscript {
44  
45  pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
46  pthread_mutex_t Context::gMessageMutex = PTHREAD_MUTEX_INITIALIZER;
47  pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
48  
initGLThread()49  bool Context::initGLThread() {
50      pthread_mutex_lock(&gInitMutex);
51  
52      int32_t ret = mHal.funcs.initGraphics(this);
53      if (ret < 0) {
54          pthread_mutex_unlock(&gInitMutex);
55          ALOGE("%p initGraphics failed", this);
56          return false;
57      }
58  
59      mSyncFd = ret;
60      pthread_mutex_unlock(&gInitMutex);
61      return true;
62  }
63  
deinitEGL()64  void Context::deinitEGL() {
65  #ifndef RS_COMPATIBILITY_LIB
66      mHal.funcs.shutdownGraphics(this);
67  #endif
68  }
69  
PushState(Context * con)70  Context::PushState::PushState(Context *con) {
71      mRsc = con;
72  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
73      if (con->mIsGraphicsContext) {
74          mFragment.set(con->getProgramFragment());
75          mVertex.set(con->getProgramVertex());
76          mStore.set(con->getProgramStore());
77          mRaster.set(con->getProgramRaster());
78          mFont.set(con->getFont());
79      }
80  #endif
81  }
82  
~PushState()83  Context::PushState::~PushState() {
84  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
85      if (mRsc->mIsGraphicsContext) {
86          mRsc->setProgramFragment(mFragment.get());
87          mRsc->setProgramVertex(mVertex.get());
88          mRsc->setProgramStore(mStore.get());
89          mRsc->setProgramRaster(mRaster.get());
90          mRsc->setFont(mFont.get());
91      }
92  #endif
93  }
94  
95  
runScript(Script * s)96  uint32_t Context::runScript(Script *s) {
97      PushState ps(this);
98  
99      uint32_t ret = s->run(this);
100      return ret;
101  }
102  
runRootScript()103  uint32_t Context::runRootScript() {
104      timerSet(RS_TIMER_SCRIPT);
105  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
106      mStateFragmentStore.mLast.clear();
107  #endif
108      watchdog.inRoot = true;
109      uint32_t ret = runScript(mRootScript.get());
110      watchdog.inRoot = false;
111  
112      return ret;
113  }
114  
getTime() const115  uint64_t Context::getTime() const {
116      struct timespec t;
117      clock_gettime(CLOCK_MONOTONIC, &t);
118      return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
119  }
120  
timerReset()121  void Context::timerReset() {
122      for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
123          mTimers[ct] = 0;
124      }
125  }
126  
timerInit()127  void Context::timerInit() {
128      mTimeLast = getTime();
129      mTimeFrame = mTimeLast;
130      mTimeLastFrame = mTimeLast;
131      mTimerActive = RS_TIMER_INTERNAL;
132      mAverageFPSFrameCount = 0;
133      mAverageFPSStartTime = mTimeLast;
134      mAverageFPS = 0;
135      timerReset();
136  }
137  
timerFrame()138  void Context::timerFrame() {
139      mTimeLastFrame = mTimeFrame;
140      mTimeFrame = getTime();
141      // Update average fps
142      const uint64_t averageFramerateInterval = 1000 * 1000000;
143      mAverageFPSFrameCount ++;
144      uint64_t inverval = mTimeFrame - mAverageFPSStartTime;
145      if (inverval >= averageFramerateInterval) {
146          inverval = inverval / 1000000;
147          mAverageFPS = (mAverageFPSFrameCount * 1000) / inverval;
148          mAverageFPSFrameCount = 0;
149          mAverageFPSStartTime = mTimeFrame;
150      }
151  }
152  
timerSet(Timers tm)153  void Context::timerSet(Timers tm) {
154      uint64_t last = mTimeLast;
155      mTimeLast = getTime();
156      mTimers[mTimerActive] += mTimeLast - last;
157      mTimerActive = tm;
158  }
159  
timerPrint()160  void Context::timerPrint() {
161      double total = 0;
162      for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
163          total += mTimers[ct];
164      }
165      uint64_t frame = mTimeFrame - mTimeLastFrame;
166      mTimeMSLastFrame = frame / 1000000;
167      mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000;
168      mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000;
169  
170  
171      if (props.mLogTimes) {
172          ALOGV("RS: Frame (%i),   Script %2.1f%% (%i),  Swap %2.1f%% (%i),  Idle %2.1f%% (%" PRIi64 "),  "
173                "Internal %2.1f%% (%" PRIi64 "), Avg fps: %u",
174               mTimeMSLastFrame,
175               100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript,
176               100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap,
177               100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
178               100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
179               mAverageFPS);
180      }
181  }
182  
setupCheck()183  bool Context::setupCheck() {
184  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
185      mFragmentStore->setup(this, &mStateFragmentStore);
186      mFragment->setup(this, &mStateFragment);
187      mRaster->setup(this, &mStateRaster);
188      mVertex->setup(this, &mStateVertex);
189      mFBOCache.setup(this);
190  #endif
191      return true;
192  }
193  
194  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
setupProgramStore()195  void Context::setupProgramStore() {
196      mFragmentStore->setup(this, &mStateFragmentStore);
197  }
198  #endif
199  
getProp(const char * str)200  static uint32_t getProp(const char *str) {
201  #ifdef __ANDROID__
202      char buf[PROP_VALUE_MAX];
203      property_get(str, buf, "0");
204      return atoi(buf);
205  #else
206      return 0;
207  #endif
208  }
209  
displayDebugStats()210  void Context::displayDebugStats() {
211  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
212      char buffer[128];
213      snprintf(buffer, sizeof(buffer), "Avg fps %u, Frame %i ms, Script %i ms",
214               mAverageFPS, mTimeMSLastFrame, mTimeMSLastScript);
215      float oldR, oldG, oldB, oldA;
216      mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA);
217      uint32_t bufferLen = strlen(buffer);
218  
219      ObjectBaseRef<Font> lastFont(getFont());
220      setFont(nullptr);
221      float shadowCol = 0.1f;
222      mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f);
223      mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6);
224  
225      mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f);
226      mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7);
227  
228      setFont(lastFont.get());
229      mStateFont.setFontColor(oldR, oldG, oldB, oldA);
230  #endif
231  }
232  
threadProc(void * vrsc)233  void * Context::threadProc(void *vrsc) {
234      Context *rsc = static_cast<Context *>(vrsc);
235  
236      rsc->mNativeThreadId = gettid();
237      rsc->props.mLogTimes = getProp("debug.rs.profile") != 0;
238      rsc->props.mLogScripts = getProp("debug.rs.script") != 0;
239      rsc->props.mLogShaders = getProp("debug.rs.shader") != 0;
240      rsc->props.mLogShadersAttr = getProp("debug.rs.shader.attributes") != 0;
241      rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms") != 0;
242      rsc->props.mLogVisual = getProp("debug.rs.visual") != 0;
243      rsc->props.mLogReduce = getProp("debug.rs.reduce");
244      rsc->props.mDebugReduceSplitAccum = getProp("debug.rs.reduce-split-accum") != 0;
245      rsc->props.mDebugMaxThreads = getProp("debug.rs.max-threads");
246  
247      if (getProp("debug.rs.debug") != 0) {
248          ALOGD("Forcing debug context due to debug.rs.debug.");
249          rsc->mContextType = RS_CONTEXT_TYPE_DEBUG;
250          rsc->mForceCpu = true;
251      }
252  
253      bool forceRSoV = getProp("debug.rs.rsov") != 0;
254      if (forceRSoV) {
255          ALOGD("Force the use of RSoV driver");
256          rsc->mForceRSoV = true;
257      }
258  
259      bool forceCpu = getProp("debug.rs.default-CPU-driver") != 0;
260      if (forceCpu) {
261          ALOGD("Skipping hardware driver and loading default CPU driver");
262          rsc->mForceCpu = true;
263      }
264  
265      rsc->mForceCpu |= rsc->mIsGraphicsContext;
266      if (!rsc->loadDriver(rsc->mForceCpu, rsc->mForceRSoV)) {
267        rsc->setError(RS_ERROR_DRIVER, "Failed loading driver");
268        return nullptr;
269      }
270  
271      if (!rsc->isSynchronous()) {
272          // Due to legacy we default to normal_graphics
273          // setPriority will make the adjustments as needed.
274          rsc->setPriority(RS_THREAD_PRIORITY_NORMAL_GRAPHICS);
275      }
276  
277  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
278      if (rsc->mIsGraphicsContext) {
279          if (!rsc->initGLThread()) {
280              rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL");
281              return nullptr;
282          }
283  
284          rsc->mStateRaster.init(rsc);
285          rsc->setProgramRaster(nullptr);
286          rsc->mStateVertex.init(rsc);
287          rsc->setProgramVertex(nullptr);
288          rsc->mStateFragment.init(rsc);
289          rsc->setProgramFragment(nullptr);
290          rsc->mStateFragmentStore.init(rsc);
291          rsc->setProgramStore(nullptr);
292          rsc->mStateFont.init(rsc);
293          rsc->setFont(nullptr);
294          rsc->mStateSampler.init(rsc);
295          rsc->mFBOCache.init(rsc);
296      }
297  #endif
298  
299      rsc->mRunning = true;
300  
301      if (rsc->isSynchronous()) {
302          return nullptr;
303      }
304  
305      if (!rsc->mIsGraphicsContext) {
306          while (!rsc->mExit) {
307              rsc->mIO.playCoreCommands(rsc, -1);
308          }
309  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
310      } else {
311          // The number of millisecond to wait between successive calls to the
312          // root function.  The special value 0 means that root should not be
313          // called again until something external changes.
314          // See compile/slang/README.rst and search for "The function **root**"
315          // for more details.
316          int whenToCallAgain = 0;
317  
318          while (!rsc->mExit) {
319              rsc->timerSet(RS_TIMER_IDLE);
320              // While it's tempting to simply have if(whenToCallAgain > 0)
321              // usleep(whentoCallAgain * 1000), doing it this way emulates
322              // more closely what the original code did.
323              if (whenToCallAgain > 16) {
324                  usleep((whenToCallAgain - 16) * 1000);
325              }
326  
327              if (!rsc->mRootScript.get() || !rsc->mHasSurface || rsc->mPaused || whenToCallAgain == 0) {
328                  rsc->mIO.playCoreCommands(rsc, -1);
329              } else {
330                  rsc->mIO.playCoreCommands(rsc, rsc->mSyncFd);
331              }
332  
333              if (rsc->mRootScript.get() && rsc->mHasSurface && !rsc->mPaused) {
334                  whenToCallAgain = rsc->runRootScript();
335  
336                  if (rsc->props.mLogVisual) {
337                      rsc->displayDebugStats();
338                  }
339                  rsc->timerSet(RS_TIMER_CLEAR_SWAP);
340                  rsc->mHal.funcs.swap(rsc);
341                  rsc->timerFrame();
342                  rsc->timerSet(RS_TIMER_INTERNAL);
343                  rsc->timerPrint();
344                  rsc->timerReset();
345              }
346          }
347  #endif
348      }
349  
350      //ALOGV("%p RS Thread exiting", rsc);
351  
352  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
353      if (rsc->mIsGraphicsContext) {
354          pthread_mutex_lock(&gInitMutex);
355          rsc->deinitEGL();
356          pthread_mutex_unlock(&gInitMutex);
357      }
358  #endif
359  
360      //ALOGV("%p RS Thread exited", rsc);
361      return nullptr;
362  }
363  
destroyWorkerThreadResources()364  void Context::destroyWorkerThreadResources() {
365      //ALOGV("destroyWorkerThreadResources 1");
366      ObjectBase::zeroAllUserRef(this);
367  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
368      if (mIsGraphicsContext) {
369           mRaster.clear();
370           mFragment.clear();
371           mVertex.clear();
372           mFragmentStore.clear();
373           mFont.clear();
374           mRootScript.clear();
375           mStateRaster.deinit(this);
376           mStateVertex.deinit(this);
377           mStateFragment.deinit(this);
378           mStateFragmentStore.deinit(this);
379           mStateFont.deinit(this);
380           mStateSampler.deinit(this);
381           mFBOCache.deinit(this);
382      }
383  #endif
384      ObjectBase::freeAllChildren(this);
385      mExit = true;
386      //ALOGV("destroyWorkerThreadResources 2");
387  }
388  
printWatchdogInfo(void * ctx)389  void Context::printWatchdogInfo(void *ctx) {
390      Context *rsc = (Context *)ctx;
391      if (rsc->watchdog.command && rsc->watchdog.file) {
392          ALOGE("RS watchdog timeout: %i  %s  line %i %s", rsc->watchdog.inRoot,
393               rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file);
394      } else {
395          ALOGE("RS watchdog timeout: %i", rsc->watchdog.inRoot);
396      }
397  }
398  
399  
setPriority(int32_t p)400  void Context::setPriority(int32_t p) {
401      switch (p) {
402      // The public API will always send NORMAL_GRAPHICS
403      // for normal, we adjust here
404      case RS_THREAD_PRIORITY_NORMAL_GRAPHICS:
405          if (!mIsGraphicsContext) {
406              if (mHal.flags & RS_CONTEXT_LOW_LATENCY) {
407                  p = RS_THREAD_PRIORITY_LOW_LATENCY;
408              } else {
409                  p = RS_THREAD_PRIORITY_NORMAL;
410              }
411          }
412          break;
413      case RS_THREAD_PRIORITY_LOW:
414          break;
415      }
416  
417      // Note: If we put this in the proper "background" policy
418      // the wallpapers can become completly unresponsive at times.
419      // This is probably not what we want for something the user is actively
420      // looking at.
421      mThreadPriority = p;
422      setpriority(PRIO_PROCESS, mNativeThreadId, p);
423      mHal.funcs.setPriority(this, mThreadPriority);
424  }
425  
Context()426  Context::Context() {
427      mDev = nullptr;
428      mRunning = false;
429      mExit = false;
430      mPaused = false;
431      mObjHead = nullptr;
432      mError = RS_ERROR_NONE;
433      mTargetSdkVersion = 14;
434      mDPI = 96;
435      mIsContextLite = false;
436      memset(&watchdog, 0, sizeof(watchdog));
437      memset(&mHal, 0, sizeof(mHal));
438      mForceCpu = false;
439      mForceRSoV = false;
440      mContextType = RS_CONTEXT_TYPE_NORMAL;
441      mOptLevel = 3;
442      mSynchronous = false;
443      mFatalErrorOccured = false;
444  
445      memset(mCacheDir, 0, sizeof(mCacheDir));
446  #ifdef RS_COMPATIBILITY_LIB
447      memset(nativeLibDir, 0, sizeof(nativeLibDir));
448  #endif
449  }
450  
setCacheDir(const char * cacheDir_arg,uint32_t length)451  void Context::setCacheDir(const char * cacheDir_arg, uint32_t length) {
452      if (length <= PATH_MAX) {
453          memcpy(mCacheDir, cacheDir_arg, length);
454          mCacheDir[length] = 0;
455          hasSetCacheDir = true;
456      } else {
457          setError(RS_ERROR_BAD_VALUE, "Invalid path");
458      }
459  }
460  
createContext(Device * dev,const RsSurfaceConfig * sc,RsContextType ct,uint32_t flags,const char * vendorDriverName)461  Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc,
462                                   RsContextType ct, uint32_t flags,
463                                   const char* vendorDriverName) {
464      Context * rsc = new Context();
465  
466      if (flags & RS_CONTEXT_LOW_LATENCY) {
467          rsc->mForceCpu = true;
468      }
469      if (flags & RS_CONTEXT_SYNCHRONOUS) {
470          rsc->mSynchronous = true;
471      }
472      rsc->mContextType = ct;
473      rsc->mHal.flags = flags;
474      rsc->mVendorDriverName = vendorDriverName;
475  
476      if (!rsc->initContext(dev, sc)) {
477          delete rsc;
478          return nullptr;
479      }
480  
481      return rsc;
482  }
483  
createContextLite()484  Context * Context::createContextLite() {
485      Context * rsc = new Context();
486      rsc->mIsContextLite = true;
487      return rsc;
488  }
489  
initContext(Device * dev,const RsSurfaceConfig * sc)490  bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
491      pthread_mutex_lock(&gInitMutex);
492  
493      if (!mIO.init()) {
494          ALOGE("Failed initializing IO Fifo");
495          pthread_mutex_unlock(&gInitMutex);
496          return false;
497      }
498      mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9);
499  
500      if (sc) {
501          mUserSurfaceConfig = *sc;
502      } else {
503          memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
504      }
505  
506      mIsGraphicsContext = sc != nullptr;
507  
508      int status;
509      pthread_attr_t threadAttr;
510  
511      pthread_mutex_unlock(&gInitMutex);
512  
513      // Global init done at this point.
514  
515      status = pthread_attr_init(&threadAttr);
516      if (status) {
517          ALOGE("Failed to init thread attribute.");
518          return false;
519      }
520  
521      mHasSurface = false;
522      mDriverName = NULL;
523  
524      timerInit();
525      timerSet(RS_TIMER_INTERNAL);
526      if (mSynchronous) {
527          threadProc(this);
528  
529          if (mError != RS_ERROR_NONE) {
530              ALOGE("Errors during thread init (sync mode)");
531              return false;
532          }
533      } else {
534          status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
535          if (status) {
536              ALOGE("Failed to start rs context thread.");
537              return false;
538          }
539          while (!mRunning && (mError == RS_ERROR_NONE)) {
540              usleep(100);
541          }
542  
543          if (mError != RS_ERROR_NONE) {
544              ALOGE("Errors during thread init");
545              return false;
546          }
547  
548          pthread_attr_destroy(&threadAttr);
549      }
550      return true;
551  }
552  
~Context()553  Context::~Context() {
554      if (!mIsContextLite) {
555          mPaused = false;
556          void *res;
557  
558          mIO.shutdown();
559          if (!mSynchronous && mRunning) {
560              // Only try to join a pthread when:
561              // 1. The Context is asynchronous.
562              // 2. pthread successfully created and running.
563              pthread_join(mThreadId, &res);
564          }
565          rsAssert(mExit);
566  
567          if (mHal.funcs.shutdownDriver && mHal.drv) {
568              mHal.funcs.shutdownDriver(this);
569          }
570      }
571  }
572  
573  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
setSurface(uint32_t w,uint32_t h,RsNativeWindow sur)574  void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
575      rsAssert(mIsGraphicsContext);
576      mHal.funcs.setSurface(this, w, h, sur);
577  
578      mHasSurface = sur != nullptr;
579      mWidth = w;
580      mHeight = h;
581  
582      if (mWidth && mHeight) {
583          mStateVertex.updateSize(this);
584          mFBOCache.updateSize();
585      }
586  }
587  
getCurrentSurfaceWidth() const588  uint32_t Context::getCurrentSurfaceWidth() const {
589      for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
590          if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
591              return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX();
592          }
593      }
594      if (mFBOCache.mHal.state.depthTarget != nullptr) {
595          return mFBOCache.mHal.state.depthTarget->getType()->getDimX();
596      }
597      return mWidth;
598  }
599  
getCurrentSurfaceHeight() const600  uint32_t Context::getCurrentSurfaceHeight() const {
601      for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
602          if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
603              return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY();
604          }
605      }
606      if (mFBOCache.mHal.state.depthTarget != nullptr) {
607          return mFBOCache.mHal.state.depthTarget->getType()->getDimY();
608      }
609      return mHeight;
610  }
611  
pause()612  void Context::pause() {
613      rsAssert(mIsGraphicsContext);
614      mPaused = true;
615  }
616  
resume()617  void Context::resume() {
618      rsAssert(mIsGraphicsContext);
619      mPaused = false;
620  }
621  
setRootScript(Script * s)622  void Context::setRootScript(Script *s) {
623      rsAssert(mIsGraphicsContext);
624      mRootScript.set(s);
625  }
626  
setProgramStore(ProgramStore * pfs)627  void Context::setProgramStore(ProgramStore *pfs) {
628      rsAssert(mIsGraphicsContext);
629      if (pfs == nullptr) {
630          mFragmentStore.set(mStateFragmentStore.mDefault);
631      } else {
632          mFragmentStore.set(pfs);
633      }
634  }
635  
setProgramFragment(ProgramFragment * pf)636  void Context::setProgramFragment(ProgramFragment *pf) {
637      rsAssert(mIsGraphicsContext);
638      if (pf == nullptr) {
639          mFragment.set(mStateFragment.mDefault);
640      } else {
641          mFragment.set(pf);
642      }
643  }
644  
setProgramRaster(ProgramRaster * pr)645  void Context::setProgramRaster(ProgramRaster *pr) {
646      rsAssert(mIsGraphicsContext);
647      if (pr == nullptr) {
648          mRaster.set(mStateRaster.mDefault);
649      } else {
650          mRaster.set(pr);
651      }
652  }
653  
setProgramVertex(ProgramVertex * pv)654  void Context::setProgramVertex(ProgramVertex *pv) {
655      rsAssert(mIsGraphicsContext);
656      if (pv == nullptr) {
657          mVertex.set(mStateVertex.mDefault);
658      } else {
659          mVertex.set(pv);
660      }
661  }
662  
setFont(Font * f)663  void Context::setFont(Font *f) {
664      rsAssert(mIsGraphicsContext);
665      if (f == nullptr) {
666          mFont.set(mStateFont.mDefault);
667      } else {
668          mFont.set(f);
669      }
670  }
671  #endif
672  
finish()673  void Context::finish() {
674      if (mHal.funcs.finish) {
675          mHal.funcs.finish(this);
676      }
677  }
678  
assignName(ObjectBase * obj,const char * name,uint32_t len)679  void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) {
680      rsAssert(!obj->getName());
681      obj->setName(name, len);
682      mNames.push_back(obj);
683  }
684  
removeName(ObjectBase * obj)685  void Context::removeName(ObjectBase *obj) {
686      for (size_t ct=0; ct < mNames.size(); ct++) {
687          if (obj == mNames[ct]) {
688              mNames.erase(mNames.begin() + ct);
689              return;
690          }
691      }
692  }
693  
peekMessageToClient(size_t * receiveLen,uint32_t * subID)694  RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) {
695      return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID);
696  }
697  
getMessageToClient(void * data,size_t * receiveLen,uint32_t * subID,size_t bufferLen)698  RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) {
699      return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen);
700  }
701  
sendMessageToClient(const void * data,RsMessageToClientType cmdID,uint32_t subID,size_t len,bool waitForSpace) const702  bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
703                                    uint32_t subID, size_t len, bool waitForSpace) const {
704  
705      pthread_mutex_lock(&gMessageMutex);
706      bool ret = mIO.sendToClient(cmdID, subID, data, len, waitForSpace);
707      pthread_mutex_unlock(&gMessageMutex);
708      return ret;
709  }
710  
initToClient()711  void Context::initToClient() {
712      while (!mRunning) {
713          usleep(100);
714      }
715  }
716  
deinitToClient()717  void Context::deinitToClient() {
718      mIO.clientShutdown();
719  }
720  
setError(RsError e,const char * msg) const721  void Context::setError(RsError e, const char *msg) const {
722      mError = e;
723  
724      if (mError >= RS_ERROR_FATAL_DEBUG) {
725          // If a FATAL error occurred, set the flag to indicate the process
726          // will be goign down
727          mFatalErrorOccured = true;
728      }
729  
730      sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true);
731  }
732  
733  
dumpDebug() const734  void Context::dumpDebug() const {
735      ALOGE("RS Context debug %p", this);
736      ALOGE("RS Context debug");
737  
738      ALOGE(" RS width %i, height %i", mWidth, mHeight);
739      ALOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
740      ALOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId);
741  }
742  
743  ///////////////////////////////////////////////////////////////////////////////////////////
744  //
745  
rsi_ContextFinish(Context * rsc)746  void rsi_ContextFinish(Context *rsc) {
747      rsc->finish();
748  }
749  
rsi_ContextBindRootScript(Context * rsc,RsScript vs)750  void rsi_ContextBindRootScript(Context *rsc, RsScript vs) {
751  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
752      Script *s = static_cast<Script *>(vs);
753      rsc->setRootScript(s);
754  #endif
755  }
756  
rsi_ContextSetCacheDir(Context * rsc,const char * cacheDir,size_t cacheDir_length)757  void rsi_ContextSetCacheDir(Context *rsc, const char *cacheDir, size_t cacheDir_length) {
758      rsc->setCacheDir(cacheDir, cacheDir_length);
759  }
760  
rsi_ContextBindSampler(Context * rsc,uint32_t slot,RsSampler vs)761  void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) {
762      Sampler *s = static_cast<Sampler *>(vs);
763  
764      if (slot > RS_MAX_SAMPLER_SLOT) {
765          ALOGE("Invalid sampler slot");
766          return;
767      }
768  
769      s->bindToContext(&rsc->mStateSampler, slot);
770  }
771  
772  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
rsi_ContextBindProgramStore(Context * rsc,RsProgramStore vpfs)773  void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) {
774      ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
775      rsc->setProgramStore(pfs);
776  }
777  
rsi_ContextBindProgramFragment(Context * rsc,RsProgramFragment vpf)778  void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) {
779      ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
780      rsc->setProgramFragment(pf);
781  }
782  
rsi_ContextBindProgramRaster(Context * rsc,RsProgramRaster vpr)783  void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) {
784      ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
785      rsc->setProgramRaster(pr);
786  }
787  
rsi_ContextBindProgramVertex(Context * rsc,RsProgramVertex vpv)788  void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) {
789      ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
790      rsc->setProgramVertex(pv);
791  }
792  
rsi_ContextBindFont(Context * rsc,RsFont vfont)793  void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
794      Font *font = static_cast<Font *>(vfont);
795      rsc->setFont(font);
796  }
797  #endif
798  
rsi_AssignName(Context * rsc,RsObjectBase obj,const char * name,size_t name_length)799  void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) {
800      ObjectBase *ob = static_cast<ObjectBase *>(obj);
801      rsc->assignName(ob, name, name_length);
802  }
803  
rsi_ObjDestroy(Context * rsc,void * optr)804  void rsi_ObjDestroy(Context *rsc, void *optr) {
805      ObjectBase *ob = static_cast<ObjectBase *>(optr);
806      rsc->removeName(ob);
807      ob->decUserRef();
808  }
809  
810  #if !defined(RS_VENDOR_LIB) && !defined(RS_COMPATIBILITY_LIB)
rsi_ContextPause(Context * rsc)811  void rsi_ContextPause(Context *rsc) {
812      rsc->pause();
813  }
814  
rsi_ContextResume(Context * rsc)815  void rsi_ContextResume(Context *rsc) {
816      rsc->resume();
817  }
818  
rsi_ContextSetSurface(Context * rsc,uint32_t w,uint32_t h,RsNativeWindow sur)819  void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
820      rsc->setSurface(w, h, sur);
821  }
822  #endif
823  
rsi_ContextSetPriority(Context * rsc,int32_t p)824  void rsi_ContextSetPriority(Context *rsc, int32_t p) {
825      rsc->setPriority(p);
826  }
827  
rsi_ContextDump(Context * rsc,int32_t bits)828  void rsi_ContextDump(Context *rsc, int32_t bits) {
829      ObjectBase::dumpAll(rsc);
830  }
831  
rsi_ContextDestroyWorker(Context * rsc)832  void rsi_ContextDestroyWorker(Context *rsc) {
833      rsc->destroyWorkerThreadResources();
834  }
835  
rsi_ContextDestroy(Context * rsc)836  void rsi_ContextDestroy(Context *rsc) {
837      //ALOGE("%p rsContextDestroy", rsc);
838      rsc->destroyWorkerThreadResources();
839      delete rsc;
840      //ALOGV("%p rsContextDestroy done", rsc);
841  }
842  
rsi_ContextPeekMessage(Context * rsc,size_t * receiveLen,size_t receiveLen_length,uint32_t * subID,size_t subID_length)843  RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
844                                             size_t * receiveLen, size_t receiveLen_length,
845                                             uint32_t * subID, size_t subID_length) {
846      return rsc->peekMessageToClient(receiveLen, subID);
847  }
848  
rsi_ContextGetMessage(Context * rsc,void * data,size_t data_length,size_t * receiveLen,size_t receiveLen_length,uint32_t * subID,size_t subID_length)849  RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
850                                            size_t * receiveLen, size_t receiveLen_length,
851                                            uint32_t * subID, size_t subID_length) {
852      rsAssert(subID_length == sizeof(uint32_t));
853      rsAssert(receiveLen_length == sizeof(size_t));
854      return rsc->getMessageToClient(data, receiveLen, subID, data_length);
855  }
856  
rsi_ContextInitToClient(Context * rsc)857  void rsi_ContextInitToClient(Context *rsc) {
858      rsc->initToClient();
859  }
860  
rsi_ContextDeinitToClient(Context * rsc)861  void rsi_ContextDeinitToClient(Context *rsc) {
862      rsc->deinitToClient();
863  }
864  
rsi_ContextSendMessage(Context * rsc,uint32_t id,const uint8_t * data,size_t len)865  void rsi_ContextSendMessage(Context *rsc, uint32_t id, const uint8_t *data, size_t len) {
866      rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, id, len, true);
867  }
868  
869  // implementation of handcode LF_ObjDestroy
870  // required so nObjDestroy can be run from finalizer without blocking
LF_ObjDestroy_handcode(const Context * rsc,RsAsyncVoidPtr objPtr)871  void LF_ObjDestroy_handcode(const Context *rsc, RsAsyncVoidPtr objPtr) {
872      if (((Context *)rsc)->isSynchronous()) {
873          rsi_ObjDestroy((Context *)rsc, objPtr);
874          return;
875      }
876  
877      // struct has two parts:
878      // RsPlaybackRemoteHeader (cmdID and bytes)
879      // RS_CMD_ObjDestroy (ptr)
880      struct destroyCmd {
881          uint32_t cmdID;
882          uint32_t bytes;
883          RsAsyncVoidPtr ptr;
884       };
885  
886      destroyCmd cmd;
887      cmd.cmdID = RS_CMD_ID_ObjDestroy;
888      cmd.bytes = sizeof(RsAsyncVoidPtr);
889      cmd.ptr = objPtr;
890      ThreadIO *io = &((Context *)rsc)->mIO;
891      io->coreWrite((void*)&cmd, sizeof(destroyCmd));
892  
893  }
894  
895  } // namespace renderscript
896  } // namespace android
897