Merge "Add RS watchdog."
This commit is contained in:
@@ -73,27 +73,27 @@ GLenum rsdKindToGLFormat(RsDataKind k) {
|
||||
}
|
||||
|
||||
|
||||
static void Update2DTexture(const Allocation *alloc, const void *ptr, uint32_t xoff, uint32_t yoff,
|
||||
uint32_t lod, RsAllocationCubemapFace face,
|
||||
uint32_t w, uint32_t h) {
|
||||
static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
|
||||
uint32_t xoff, uint32_t yoff, uint32_t lod,
|
||||
RsAllocationCubemapFace face, uint32_t w, uint32_t h) {
|
||||
DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
|
||||
|
||||
rsAssert(drv->textureID);
|
||||
glBindTexture(drv->glTarget, drv->textureID);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
|
||||
RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
|
||||
GLenum t = GL_TEXTURE_2D;
|
||||
if (alloc->mHal.state.hasFaces) {
|
||||
t = gFaceOrder[face];
|
||||
}
|
||||
glTexSubImage2D(t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
|
||||
RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
|
||||
}
|
||||
|
||||
|
||||
static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
|
||||
DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
|
||||
|
||||
glBindTexture(drv->glTarget, drv->textureID);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
|
||||
RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
uint32_t faceCount = 1;
|
||||
if (alloc->mHal.state.hasFaces) {
|
||||
@@ -112,12 +112,12 @@ static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool is
|
||||
}
|
||||
|
||||
if (isFirstUpload) {
|
||||
glTexImage2D(t, lod, drv->glFormat,
|
||||
RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat,
|
||||
alloc->mHal.state.type->getLODDimX(lod),
|
||||
alloc->mHal.state.type->getLODDimY(lod),
|
||||
0, drv->glFormat, drv->glType, p);
|
||||
} else {
|
||||
glTexSubImage2D(t, lod, 0, 0,
|
||||
RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0,
|
||||
alloc->mHal.state.type->getLODDimX(lod),
|
||||
alloc->mHal.state.type->getLODDimY(lod),
|
||||
drv->glFormat, drv->glType, p);
|
||||
@@ -126,7 +126,7 @@ static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool is
|
||||
}
|
||||
|
||||
if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
|
||||
glGenerateMipmap(drv->glTarget);
|
||||
RSD_CALL_GL(glGenerateMipmap, drv->glTarget);
|
||||
}
|
||||
rsdGLCheckError(rsc, "Upload2DTexture");
|
||||
}
|
||||
@@ -145,7 +145,7 @@ static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
|
||||
bool isFirstUpload = false;
|
||||
|
||||
if (!drv->textureID) {
|
||||
glGenTextures(1, &drv->textureID);
|
||||
RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
|
||||
isFirstUpload = true;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
|
||||
}
|
||||
|
||||
if (!drv->renderTargetID) {
|
||||
glGenRenderbuffers(1, &drv->renderTargetID);
|
||||
RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID);
|
||||
|
||||
if (!drv->renderTargetID) {
|
||||
// This should generally not happen
|
||||
@@ -176,8 +176,8 @@ static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
|
||||
rsc->dumpDebug();
|
||||
return;
|
||||
}
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, drv->renderTargetID);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, drv->glFormat,
|
||||
RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID);
|
||||
RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat,
|
||||
alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY);
|
||||
}
|
||||
rsdGLCheckError(rsc, "AllocateRenderTarget");
|
||||
@@ -192,17 +192,17 @@ static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
|
||||
//alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
|
||||
|
||||
if (!drv->bufferID) {
|
||||
glGenBuffers(1, &drv->bufferID);
|
||||
RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID);
|
||||
}
|
||||
if (!drv->bufferID) {
|
||||
LOGE("Upload to buffer object failed");
|
||||
drv->uploadDeferred = true;
|
||||
return;
|
||||
}
|
||||
glBindBuffer(drv->glTarget, drv->bufferID);
|
||||
glBufferData(drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
|
||||
RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID);
|
||||
RSD_CALL_GL(glBufferData, drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
|
||||
drv->mallocPtr, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(drv->glTarget, 0);
|
||||
RSD_CALL_GL(glBindBuffer, drv->glTarget, 0);
|
||||
rsdGLCheckError(rsc, "UploadToBufferObject");
|
||||
}
|
||||
|
||||
@@ -261,11 +261,11 @@ void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
|
||||
//mBufferID = 0;
|
||||
}
|
||||
if (drv->textureID) {
|
||||
glDeleteTextures(1, &drv->textureID);
|
||||
RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
|
||||
drv->textureID = 0;
|
||||
}
|
||||
if (drv->renderTargetID) {
|
||||
glDeleteRenderbuffers(1, &drv->renderTargetID);
|
||||
RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
|
||||
drv->renderTargetID = 0;
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc
|
||||
drv->readBackFBO->setActive(rsc);
|
||||
|
||||
// Do the readback
|
||||
glReadPixels(0, 0, alloc->getType()->getDimX(), alloc->getType()->getDimY(),
|
||||
RSD_CALL_GL(glReadPixels, 0, 0, alloc->getType()->getDimX(), alloc->getType()->getDimY(),
|
||||
drv->glFormat, drv->glType, alloc->getPtr());
|
||||
|
||||
// Revert framebuffer to its original
|
||||
@@ -414,7 +414,7 @@ void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
|
||||
}
|
||||
drv->uploadDeferred = true;
|
||||
} else {
|
||||
Update2DTexture(alloc, data, xoff, yoff, lod, face, w, h);
|
||||
Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "rsdFrameBufferObj.h"
|
||||
#include "rsdAllocation.h"
|
||||
#include "rsdGL.h"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
@@ -124,9 +125,9 @@ void RsdFrameBufferObj::setActive(const Context *rsc) {
|
||||
bool framebuffer = renderToFramebuffer();
|
||||
if (!framebuffer) {
|
||||
if(mFBOId == 0) {
|
||||
glGenFramebuffers(1, &mFBOId);
|
||||
RSD_CALL_GL(glGenFramebuffers, 1, &mFBOId);
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBOId);
|
||||
RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, mFBOId);
|
||||
|
||||
if (mDirty) {
|
||||
setDepthAttachment();
|
||||
@@ -134,10 +135,10 @@ void RsdFrameBufferObj::setActive(const Context *rsc) {
|
||||
mDirty = false;
|
||||
}
|
||||
|
||||
glViewport(0, 0, mWidth, mHeight);
|
||||
RSD_CALL_GL(glViewport, 0, 0, mWidth, mHeight);
|
||||
checkError(rsc);
|
||||
} else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
|
||||
RSD_CALL_GL(glBindFramebuffer, GL_FRAMEBUFFER, 0);
|
||||
RSD_CALL_GL(glViewport, 0, 0, rsc->getWidth(), rsc->getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,18 +135,19 @@ void rsdGLShutdown(const Context *rsc) {
|
||||
LOGV("%p, deinitEGL", rsc);
|
||||
|
||||
if (dc->gl.egl.context != EGL_NO_CONTEXT) {
|
||||
eglMakeCurrent(dc->gl.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surfaceDefault);
|
||||
RSD_CALL_GL(eglMakeCurrent, dc->gl.egl.display,
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surfaceDefault);
|
||||
if (dc->gl.egl.surface != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
|
||||
RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surface);
|
||||
}
|
||||
eglDestroyContext(dc->gl.egl.display, dc->gl.egl.context);
|
||||
RSD_CALL_GL(eglDestroyContext, dc->gl.egl.display, dc->gl.egl.context);
|
||||
checkEglError("eglDestroyContext");
|
||||
}
|
||||
|
||||
gGLContextCount--;
|
||||
if (!gGLContextCount) {
|
||||
eglTerminate(dc->gl.egl.display);
|
||||
RSD_CALL_GL(eglTerminate, dc->gl.egl.display);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,21 +203,25 @@ bool rsdGLInit(const Context *rsc) {
|
||||
rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
|
||||
|
||||
LOGV("%p initEGL start", rsc);
|
||||
rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__);
|
||||
dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
checkEglError("eglGetDisplay");
|
||||
|
||||
eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
|
||||
RSD_CALL_GL(eglInitialize, dc->gl.egl.display,
|
||||
&dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
|
||||
checkEglError("eglInitialize");
|
||||
|
||||
EGLBoolean ret;
|
||||
|
||||
EGLint numConfigs = -1, n = 0;
|
||||
rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
|
||||
ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
|
||||
checkEglError("eglGetConfigs", ret);
|
||||
|
||||
if (numConfigs) {
|
||||
EGLConfig* const configs = new EGLConfig[numConfigs];
|
||||
|
||||
rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
|
||||
ret = eglChooseConfig(dc->gl.egl.display,
|
||||
configAttribs, configs, numConfigs, &n);
|
||||
if (!ret || !n) {
|
||||
@@ -261,32 +266,38 @@ bool rsdGLInit(const Context *rsc) {
|
||||
}
|
||||
//}
|
||||
|
||||
rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__);
|
||||
dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
|
||||
EGL_NO_CONTEXT, context_attribs2);
|
||||
checkEglError("eglCreateContext");
|
||||
if (dc->gl.egl.context == EGL_NO_CONTEXT) {
|
||||
LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
|
||||
rsc->setWatchdogGL(NULL, 0, NULL);
|
||||
return false;
|
||||
}
|
||||
gGLContextCount++;
|
||||
|
||||
|
||||
EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
|
||||
rsc->setWatchdogGL("eglCreatePbufferSurface", __LINE__, __FILE__);
|
||||
dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config,
|
||||
pbuffer_attribs);
|
||||
checkEglError("eglCreatePbufferSurface");
|
||||
if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
|
||||
LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
|
||||
rsdGLShutdown(rsc);
|
||||
rsc->setWatchdogGL(NULL, 0, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
|
||||
ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
|
||||
dc->gl.egl.surfaceDefault, dc->gl.egl.context);
|
||||
if (ret == EGL_FALSE) {
|
||||
LOGE("eglMakeCurrent returned EGL_FALSE");
|
||||
checkEglError("eglMakeCurrent", ret);
|
||||
rsdGLShutdown(rsc);
|
||||
rsc->setWatchdogGL(NULL, 0, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -314,6 +325,7 @@ bool rsdGLInit(const Context *rsc) {
|
||||
if (!verptr) {
|
||||
LOGE("Error, OpenGL ES Lite not supported");
|
||||
rsdGLShutdown(rsc);
|
||||
rsc->setWatchdogGL(NULL, 0, NULL);
|
||||
return false;
|
||||
} else {
|
||||
sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
|
||||
@@ -352,6 +364,7 @@ bool rsdGLInit(const Context *rsc) {
|
||||
dc->gl.currentFrameBuffer = NULL;
|
||||
|
||||
LOGV("initGLThread end %p", rsc);
|
||||
rsc->setWatchdogGL(NULL, 0, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -363,10 +376,12 @@ bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow
|
||||
// WAR: Some drivers fail to handle 0 size surfaces correcntly.
|
||||
// Use the pbuffer to avoid this pitfall.
|
||||
if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) {
|
||||
rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
|
||||
ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
|
||||
dc->gl.egl.surfaceDefault, dc->gl.egl.context);
|
||||
checkEglError("eglMakeCurrent", ret);
|
||||
|
||||
rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__);
|
||||
ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
|
||||
checkEglError("eglDestroySurface", ret);
|
||||
|
||||
@@ -385,6 +400,7 @@ bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow
|
||||
dc->gl.width = w;
|
||||
dc->gl.height = h;
|
||||
|
||||
rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__);
|
||||
dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
|
||||
dc->gl.wndSurface, NULL);
|
||||
checkEglError("eglCreateWindowSurface");
|
||||
@@ -392,16 +408,18 @@ bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow
|
||||
LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
|
||||
}
|
||||
|
||||
rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
|
||||
ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
|
||||
dc->gl.egl.surface, dc->gl.egl.context);
|
||||
checkEglError("eglMakeCurrent", ret);
|
||||
}
|
||||
rsc->setWatchdogGL(NULL, 0, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void rsdGLSwap(const android::renderscript::Context *rsc) {
|
||||
RsdHal *dc = (RsdHal *)rsc->mHal.drv;
|
||||
eglSwapBuffers(dc->gl.egl.display, dc->gl.egl.surface);
|
||||
RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
|
||||
}
|
||||
|
||||
void rsdGLCheckError(const android::renderscript::Context *rsc,
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <rs_hal.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#define RSD_CALL_GL(x, ...) rsc->setWatchdogGL(#x, __LINE__, __FILE__); x(__VA_ARGS__); rsc->setWatchdogGL(NULL, 0, NULL)
|
||||
|
||||
class RsdShaderCache;
|
||||
class RsdVertexArrayState;
|
||||
class RsdFrameBufferObj;
|
||||
@@ -73,7 +75,6 @@ typedef struct RsdGLRec {
|
||||
} RsdGL;
|
||||
|
||||
|
||||
|
||||
bool rsdGLInit(const android::renderscript::Context *rsc);
|
||||
void rsdGLShutdown(const android::renderscript::Context *rsc);
|
||||
bool rsdGLSetSurface(const android::renderscript::Context *rsc,
|
||||
|
||||
@@ -130,7 +130,8 @@ bool RsdMeshObj::init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
|
||||
void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex,
|
||||
uint32_t start, uint32_t len) const {
|
||||
if (len < 1 || primIndex >= mRSMesh->mHal.state.primitivesCount || mAttribCount == 0) {
|
||||
LOGE("Invalid mesh or parameters");
|
||||
return;
|
||||
@@ -171,14 +172,16 @@ void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, ui
|
||||
}
|
||||
|
||||
if (drvAlloc->bufferID) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drvAlloc->bufferID);
|
||||
glDrawElements(mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
|
||||
RSD_CALL_GL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, drvAlloc->bufferID);
|
||||
RSD_CALL_GL(glDrawElements, mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT,
|
||||
(uint16_t *)(start * 2));
|
||||
} else {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glDrawElements(mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT, drvAlloc->mallocPtr);
|
||||
RSD_CALL_GL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
RSD_CALL_GL(glDrawElements, mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT,
|
||||
drvAlloc->mallocPtr);
|
||||
}
|
||||
} else {
|
||||
glDrawArrays(mGLPrimitives[primIndex], start, len);
|
||||
RSD_CALL_GL(glDrawArrays, mGLPrimitives[primIndex], start, len);
|
||||
}
|
||||
|
||||
rsdGLCheckError(rsc, "Mesh::renderPrimitiveRange");
|
||||
|
||||
@@ -32,18 +32,18 @@ bool rsdProgramRasterInit(const Context *, const ProgramRaster *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void rsdProgramRasterSetActive(const Context *, const ProgramRaster *pr) {
|
||||
void rsdProgramRasterSetActive(const Context *rsc, const ProgramRaster *pr) {
|
||||
switch (pr->mHal.state.cull) {
|
||||
case RS_CULL_BACK:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
RSD_CALL_GL(glEnable, GL_CULL_FACE);
|
||||
RSD_CALL_GL(glCullFace, GL_BACK);
|
||||
break;
|
||||
case RS_CULL_FRONT:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
RSD_CALL_GL(glEnable, GL_CULL_FACE);
|
||||
RSD_CALL_GL(glCullFace, GL_FRONT);
|
||||
break;
|
||||
case RS_CULL_NONE:
|
||||
glDisable(GL_CULL_FACE);
|
||||
RSD_CALL_GL(glDisable, GL_CULL_FACE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,29 +156,29 @@ error:
|
||||
void rsdProgramStoreSetActive(const Context *rsc, const ProgramStore *ps) {
|
||||
DrvProgramStore *drv = (DrvProgramStore *)ps->mHal.drv;
|
||||
|
||||
glColorMask(ps->mHal.state.colorRWriteEnable,
|
||||
RSD_CALL_GL(glColorMask, ps->mHal.state.colorRWriteEnable,
|
||||
ps->mHal.state.colorGWriteEnable,
|
||||
ps->mHal.state.colorBWriteEnable,
|
||||
ps->mHal.state.colorAWriteEnable);
|
||||
|
||||
if (drv->blendEnable) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(drv->blendSrc, drv->blendDst);
|
||||
RSD_CALL_GL(glEnable, GL_BLEND);
|
||||
RSD_CALL_GL(glBlendFunc, drv->blendSrc, drv->blendDst);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
RSD_CALL_GL(glDisable, GL_BLEND);
|
||||
}
|
||||
|
||||
if (rsc->mUserSurfaceConfig.depthMin > 0) {
|
||||
glDepthMask(ps->mHal.state.depthWriteEnable);
|
||||
RSD_CALL_GL(glDepthMask, ps->mHal.state.depthWriteEnable);
|
||||
if (drv->depthTestEnable || ps->mHal.state.depthWriteEnable) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(drv->depthFunc);
|
||||
RSD_CALL_GL(glEnable, GL_DEPTH_TEST);
|
||||
RSD_CALL_GL(glDepthFunc, drv->depthFunc);
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
RSD_CALL_GL(glDisable, GL_DEPTH_TEST);
|
||||
}
|
||||
} else {
|
||||
glDepthMask(false);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
RSD_CALL_GL(glDepthMask, false);
|
||||
RSD_CALL_GL(glDisable, GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -190,9 +190,9 @@ void rsdProgramStoreSetActive(const Context *rsc, const ProgramStore *ps) {
|
||||
*/
|
||||
|
||||
if (ps->mHal.state.ditherEnable) {
|
||||
glEnable(GL_DITHER);
|
||||
RSD_CALL_GL(glEnable, GL_DITHER);
|
||||
} else {
|
||||
glDisable(GL_DITHER);
|
||||
RSD_CALL_GL(glDisable, GL_DITHER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,22 +178,22 @@ bool RsdShader::loadShader(const Context *rsc) {
|
||||
|
||||
if (mShaderID) {
|
||||
const char * ss = mShader.string();
|
||||
glShaderSource(mShaderID, 1, &ss, NULL);
|
||||
glCompileShader(mShaderID);
|
||||
RSD_CALL_GL(glShaderSource, mShaderID, 1, &ss, NULL);
|
||||
RSD_CALL_GL(glCompileShader, mShaderID);
|
||||
|
||||
GLint compiled = 0;
|
||||
glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
|
||||
RSD_CALL_GL(glGetShaderiv, mShaderID, GL_COMPILE_STATUS, &compiled);
|
||||
if (!compiled) {
|
||||
GLint infoLen = 0;
|
||||
glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
|
||||
RSD_CALL_GL(glGetShaderiv, mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
|
||||
if (infoLen) {
|
||||
char* buf = (char*) malloc(infoLen);
|
||||
if (buf) {
|
||||
glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
|
||||
RSD_CALL_GL(glGetShaderInfoLog, mShaderID, infoLen, NULL, buf);
|
||||
LOGE("Could not compile shader \n%s\n", buf);
|
||||
free(buf);
|
||||
}
|
||||
glDeleteShader(mShaderID);
|
||||
RSD_CALL_GL(glDeleteShader, mShaderID);
|
||||
mShaderID = 0;
|
||||
rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
|
||||
return false;
|
||||
@@ -297,24 +297,24 @@ void RsdShader::setUniform(const Context *rsc, const Element *field, const float
|
||||
int32_t slot, uint32_t arraySize ) {
|
||||
RsDataType dataType = field->getType();
|
||||
if (dataType == RS_TYPE_MATRIX_4X4) {
|
||||
glUniformMatrix4fv(slot, arraySize, GL_FALSE, fd);
|
||||
RSD_CALL_GL(glUniformMatrix4fv, slot, arraySize, GL_FALSE, fd);
|
||||
} else if (dataType == RS_TYPE_MATRIX_3X3) {
|
||||
glUniformMatrix3fv(slot, arraySize, GL_FALSE, fd);
|
||||
RSD_CALL_GL(glUniformMatrix3fv, slot, arraySize, GL_FALSE, fd);
|
||||
} else if (dataType == RS_TYPE_MATRIX_2X2) {
|
||||
glUniformMatrix2fv(slot, arraySize, GL_FALSE, fd);
|
||||
RSD_CALL_GL(glUniformMatrix2fv, slot, arraySize, GL_FALSE, fd);
|
||||
} else {
|
||||
switch (field->getComponent().getVectorSize()) {
|
||||
case 1:
|
||||
glUniform1fv(slot, arraySize, fd);
|
||||
RSD_CALL_GL(glUniform1fv, slot, arraySize, fd);
|
||||
break;
|
||||
case 2:
|
||||
glUniform2fv(slot, arraySize, fd);
|
||||
RSD_CALL_GL(glUniform2fv, slot, arraySize, fd);
|
||||
break;
|
||||
case 3:
|
||||
glUniform3fv(slot, arraySize, fd);
|
||||
RSD_CALL_GL(glUniform3fv, slot, arraySize, fd);
|
||||
break;
|
||||
case 4:
|
||||
glUniform4fv(slot, arraySize, fd);
|
||||
RSD_CALL_GL(glUniform4fv, slot, arraySize, fd);
|
||||
break;
|
||||
default:
|
||||
rsAssert(0);
|
||||
@@ -351,37 +351,44 @@ void RsdShader::setupSampler(const Context *rsc, const Sampler *s, const Allocat
|
||||
if (tex->getHasGraphicsMipmaps() &&
|
||||
(dc->gl.gl.GL_NV_texture_npot_2D_mipmap || dc->gl.gl.GL_IMG_texture_npot)) {
|
||||
if (dc->gl.gl.GL_NV_texture_npot_2D_mipmap) {
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[s->mHal.state.minFilter]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
|
||||
trans[s->mHal.state.minFilter]);
|
||||
} else {
|
||||
switch (trans[s->mHal.state.minFilter]) {
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_NEAREST);
|
||||
break;
|
||||
default:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[s->mHal.state.minFilter]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
|
||||
trans[s->mHal.state.minFilter]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[s->mHal.state.minFilter]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
|
||||
transNP[s->mHal.state.minFilter]);
|
||||
}
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, transNP[s->mHal.state.magFilter]);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, transNP[s->mHal.state.wrapS]);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, transNP[s->mHal.state.wrapT]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MAG_FILTER,
|
||||
transNP[s->mHal.state.magFilter]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_S, transNP[s->mHal.state.wrapS]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_T, transNP[s->mHal.state.wrapT]);
|
||||
} else {
|
||||
if (tex->getHasGraphicsMipmaps()) {
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[s->mHal.state.minFilter]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
|
||||
trans[s->mHal.state.minFilter]);
|
||||
} else {
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[s->mHal.state.minFilter]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
|
||||
transNP[s->mHal.state.minFilter]);
|
||||
}
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, trans[s->mHal.state.magFilter]);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, trans[s->mHal.state.wrapS]);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, trans[s->mHal.state.wrapT]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MAG_FILTER, trans[s->mHal.state.magFilter]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_S, trans[s->mHal.state.wrapS]);
|
||||
RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_T, trans[s->mHal.state.wrapT]);
|
||||
}
|
||||
|
||||
float anisoValue = rsMin(dc->gl.gl.EXT_texture_max_aniso, s->mHal.state.aniso);
|
||||
if (dc->gl.gl.EXT_texture_max_aniso > 1.0f) {
|
||||
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
|
||||
RSD_CALL_GL(glTexParameterf, target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
|
||||
}
|
||||
|
||||
rsdGLCheckError(rsc, "Sampler::setup tex env");
|
||||
@@ -404,12 +411,12 @@ void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) {
|
||||
}
|
||||
|
||||
for (uint32_t ct=0; ct < numTexturesToBind; ct++) {
|
||||
glActiveTexture(GL_TEXTURE0 + ct);
|
||||
glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
|
||||
RSD_CALL_GL(glActiveTexture, GL_TEXTURE0 + ct);
|
||||
RSD_CALL_GL(glUniform1i, sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
|
||||
|
||||
if (!mRSProgram->mHal.state.textures[ct].get()) {
|
||||
// if nothing is bound, reset to default GL texture
|
||||
glBindTexture(mTextureTargets[ct], 0);
|
||||
RSD_CALL_GL(glBindTexture, mTextureTargets[ct], 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -418,21 +425,22 @@ void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) {
|
||||
LOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct);
|
||||
rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
|
||||
}
|
||||
glBindTexture(drvTex->glTarget, drvTex->textureID);
|
||||
RSD_CALL_GL(glBindTexture, drvTex->glTarget, drvTex->textureID);
|
||||
rsdGLCheckError(rsc, "ProgramFragment::setup tex bind");
|
||||
if (mRSProgram->mHal.state.samplers[ct].get()) {
|
||||
setupSampler(rsc, mRSProgram->mHal.state.samplers[ct].get(), mRSProgram->mHal.state.textures[ct].get());
|
||||
setupSampler(rsc, mRSProgram->mHal.state.samplers[ct].get(),
|
||||
mRSProgram->mHal.state.textures[ct].get());
|
||||
} else {
|
||||
glTexParameteri(drvTex->glTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(drvTex->glTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(drvTex->glTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(drvTex->glTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
RSD_CALL_GL(glTexParameteri, drvTex->glTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
rsdGLCheckError(rsc, "ProgramFragment::setup tex env");
|
||||
}
|
||||
rsdGLCheckError(rsc, "ProgramFragment::setup uniforms");
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
RSD_CALL_GL(glActiveTexture, GL_TEXTURE0);
|
||||
mDirty = false;
|
||||
rsdGLCheckError(rsc, "ProgramFragment::setup");
|
||||
}
|
||||
@@ -442,7 +450,8 @@ void RsdShader::setupUserConstants(const Context *rsc, RsdShaderCache *sc, bool
|
||||
for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
|
||||
Allocation *alloc = mRSProgram->mHal.state.constants[ct].get();
|
||||
if (!alloc) {
|
||||
LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct);
|
||||
LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set",
|
||||
(uint32_t)this, ct);
|
||||
rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
|
||||
continue;
|
||||
}
|
||||
@@ -470,7 +479,8 @@ void RsdShader::setupUserConstants(const Context *rsc, RsdShaderCache *sc, bool
|
||||
arraySize = sc->fragUniformSize(uidx);
|
||||
}
|
||||
if (rsc->props.mLogShadersUniforms) {
|
||||
LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
|
||||
LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s",
|
||||
slot, offset, ct, field, uidx, fieldName);
|
||||
}
|
||||
uidx ++;
|
||||
if (slot < 0) {
|
||||
@@ -528,7 +538,8 @@ void RsdShader::initAttribAndUniformArray() {
|
||||
}
|
||||
}
|
||||
|
||||
void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix) {
|
||||
void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths,
|
||||
uint32_t *count, const char *prefix) {
|
||||
rsAssert(e->getFieldCount());
|
||||
for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
|
||||
const Element *ce = e->getField(ct);
|
||||
|
||||
@@ -86,7 +86,9 @@ uint32_t Context::runScript(Script *s) {
|
||||
uint32_t Context::runRootScript() {
|
||||
timerSet(RS_TIMER_SCRIPT);
|
||||
mStateFragmentStore.mLast.clear();
|
||||
watchdog.inRoot = true;
|
||||
uint32_t ret = runScript(mRootScript.get());
|
||||
watchdog.inRoot = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -317,6 +319,13 @@ void Context::destroyWorkerThreadResources() {
|
||||
mExit = true;
|
||||
}
|
||||
|
||||
void Context::printWatchdogInfo(void *ctx) {
|
||||
Context *rsc = (Context *)ctx;
|
||||
LOGE("RS watchdog timeout: %i %s line %i %s", rsc->watchdog.inRoot,
|
||||
rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file);
|
||||
}
|
||||
|
||||
|
||||
void Context::setPriority(int32_t p) {
|
||||
// Note: If we put this in the proper "background" policy
|
||||
// the wallpapers can become completly unresponsive at times.
|
||||
@@ -368,6 +377,7 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
|
||||
pthread_mutex_lock(&gInitMutex);
|
||||
|
||||
mIO.init();
|
||||
mIO.setTimoutCallback(printWatchdogInfo, this, 2e9);
|
||||
|
||||
dev->addContext(this);
|
||||
mDev = dev;
|
||||
|
||||
@@ -191,6 +191,19 @@ public:
|
||||
bool mLogVisual;
|
||||
} props;
|
||||
|
||||
mutable struct {
|
||||
bool inRoot;
|
||||
const char *command;
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
} watchdog;
|
||||
static void printWatchdogInfo(void *ctx);
|
||||
void setWatchdogGL(const char *cmd, uint32_t line, const char *file) const {
|
||||
watchdog.command = cmd;
|
||||
watchdog.file = file;
|
||||
watchdog.line = line;
|
||||
}
|
||||
|
||||
void dumpDebug() const;
|
||||
void setError(RsError e, const char *msg = NULL) const;
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ using namespace android;
|
||||
using namespace android::renderscript;
|
||||
|
||||
LocklessCommandFifo::LocklessCommandFifo() : mBuffer(0), mInitialized(false) {
|
||||
mTimeoutCallback = NULL;
|
||||
mTimeoutCallbackData = NULL;
|
||||
mTimeoutWait = 0;
|
||||
}
|
||||
|
||||
LocklessCommandFifo::~LocklessCommandFifo() {
|
||||
@@ -125,11 +128,21 @@ void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes) {
|
||||
void LocklessCommandFifo::flush() {
|
||||
//dumpState("flush 1");
|
||||
while (mPut != mGet) {
|
||||
mSignalToControl.wait();
|
||||
while (!mSignalToControl.wait(mTimeoutWait)) {
|
||||
if (mTimeoutCallback) {
|
||||
mTimeoutCallback(mTimeoutCallbackData);
|
||||
}
|
||||
}
|
||||
}
|
||||
//dumpState("flush 2");
|
||||
}
|
||||
|
||||
void LocklessCommandFifo::setTimoutCallback(void (*cbk)(void *), void *data, uint64_t timeout) {
|
||||
mTimeoutCallback = cbk;
|
||||
mTimeoutCallbackData = data;
|
||||
mTimeoutWait = timeout;
|
||||
}
|
||||
|
||||
bool LocklessCommandFifo::wait(uint64_t timeout) {
|
||||
while (isEmpty() && !mInShutdown) {
|
||||
mSignalToControl.set();
|
||||
|
||||
@@ -34,6 +34,7 @@ class LocklessCommandFifo {
|
||||
public:
|
||||
bool init(uint32_t size);
|
||||
void shutdown();
|
||||
void setTimoutCallback(void (*)(void *), void *, uint64_t timeout);
|
||||
|
||||
void printDebugData() const;
|
||||
|
||||
@@ -71,6 +72,10 @@ public:
|
||||
|
||||
private:
|
||||
void dumpState(const char *) const;
|
||||
|
||||
void (*mTimeoutCallback)(void *);
|
||||
void * mTimeoutCallbackData;
|
||||
uint64_t mTimeoutWait;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ void rsrDrawQuadTexCoords(Context *rsc, Script *sc,
|
||||
RsdVertexArray va(attribs, 2);
|
||||
va.setup(rsc);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
RSD_CALL_GL(glDrawArrays, GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
void rsrDrawQuad(Context *rsc, Script *sc,
|
||||
@@ -245,7 +245,7 @@ void rsrColor(Context *rsc, Script *sc, float r, float g, float b, float a) {
|
||||
}
|
||||
|
||||
void rsrFinish(Context *rsc, Script *sc) {
|
||||
glFinish();
|
||||
RSD_CALL_GL(glFinish);
|
||||
}
|
||||
|
||||
|
||||
@@ -253,16 +253,16 @@ void rsrClearColor(Context *rsc, Script *sc, float r, float g, float b, float a)
|
||||
rsc->mFBOCache.setup(rsc);
|
||||
rsc->setupProgramStore();
|
||||
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
RSD_CALL_GL(glClearColor, r, g, b, a);
|
||||
RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void rsrClearDepth(Context *rsc, Script *sc, float v) {
|
||||
rsc->mFBOCache.setup(rsc);
|
||||
rsc->setupProgramStore();
|
||||
|
||||
glClearDepthf(v);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
RSD_CALL_GL(glClearDepthf, v);
|
||||
RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
uint32_t rsrGetWidth(Context *rsc, Script *sc) {
|
||||
|
||||
@@ -112,6 +112,10 @@ void ThreadIO::coreGetReturn(void *data, size_t dataLen) {
|
||||
memcpy(data, &mToCoreRet, dataLen);
|
||||
}
|
||||
|
||||
void ThreadIO::setTimoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) {
|
||||
mToCore.setTimoutCallback(cb, dat, timeout);
|
||||
}
|
||||
|
||||
|
||||
bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait) {
|
||||
bool ret = false;
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
// Returns true if any commands were processed.
|
||||
bool playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait);
|
||||
|
||||
void setTimoutCallback(void (*)(void *), void *, uint64_t timeout);
|
||||
//LocklessCommandFifo mToCore;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user