Commit dde7f446 by Nicolas Capens Committed by Nicolas Capens

Eliminate GL resource manager.

Bug 18591036 Change-Id: I436c8cc4b30d41010db7ab4b10be0c74217b9f15 Reviewed-on: https://swiftshader-review.googlesource.com/1550Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 53fae3e9
......@@ -16,9 +16,6 @@ class Context
public:
virtual void destroy() = 0;
virtual void makeCurrent(Surface *surface) = 0;
virtual void bindTexImage(Surface *surface) = 0;
virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel) = 0;
virtual Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel) = 0;
virtual int getClientVersion() = 0;
};
}
......
......@@ -88,13 +88,7 @@ void Surface::release()
mDepthStencil->release();
mDepthStencil = NULL;
}
if(mTexture)
{
mTexture->releaseTexImage();
mTexture = NULL;
}
if(backBuffer)
{
backBuffer->release();
......
......@@ -6,7 +6,6 @@ namespace egl
class Texture2D
{
public:
virtual void releaseTexImage() = 0;
};
}
......
......@@ -629,103 +629,6 @@ EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLi
return EGL_FALSE;
}
EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if(!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
if(buffer != EGL_BACK_BUFFER)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
if(surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
if(eglSurface->getBoundTexture())
{
return error(EGL_BAD_ACCESS, EGL_FALSE);
}
if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return error(EGL_BAD_MATCH, EGL_FALSE);
}
egl::Context *context = static_cast<egl::Context*>(egl::getCurrentContext());
if(context)
{
context->bindTexImage(eglSurface);
}
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_FALSE);
}
return EGL_FALSE;
}
EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
if(!validateSurface(display, eglSurface))
{
return EGL_FALSE;
}
if(buffer != EGL_BACK_BUFFER)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
if(surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return error(EGL_BAD_SURFACE, EGL_FALSE);
}
if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return error(EGL_BAD_MATCH, EGL_FALSE);
}
egl::Texture2D *texture = eglSurface->getBoundTexture();
if(texture)
{
texture->releaseTexImage();
}
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_FALSE);
}
return EGL_FALSE;
}
EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
TRACE("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
......@@ -1078,149 +981,15 @@ EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNat
return EGL_FALSE;
}
EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Context *context = static_cast<egl::Context*>(ctx);
if(!validateDisplay(display))
{
return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
}
if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
{
return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
}
EGLenum imagePreserved = EGL_FALSE;
GLuint textureLevel = 0;
if(attrib_list)
{
for(const EGLint *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
{
if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
{
imagePreserved = attribute[1];
}
else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
{
textureLevel = attribute[1];
}
else
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
}
}
}
GLuint name = reinterpret_cast<intptr_t>(buffer);
if(name == 0)
{
return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
}
EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
if(validationResult != EGL_SUCCESS)
{
return error(validationResult, EGL_NO_IMAGE_KHR);
}
egl::Image *image = context->createSharedImage(target, name, textureLevel);
if(!image)
{
return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
}
if(image->getMultiSampleDepth() > 1)
{
return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
}
return success((EGLImageKHR)image);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_NO_IMAGE_KHR);
}
return EGL_NO_IMAGE_KHR;
}
EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
{
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
if(!validateDisplay(display))
{
return error(EGL_BAD_DISPLAY, EGL_FALSE);
}
if(!image)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
egl::Image *glImage = static_cast<egl::Image*>(image);
glImage->release();
return success(EGL_TRUE);
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, EGL_FALSE);
}
return EGL_FALSE;
}
__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
{
TRACE("(const char *procname = \"%s\")", procname);
try
{
struct Extension
{
const char *name;
__eglMustCastToProperFunctionPointerType address;
};
static const Extension eglExtensions[] =
{
#define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
EXTENSION(eglCreateImageKHR),
EXTENSION(eglDestroyImageKHR),
#undef EXTENSION
};
for(int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
{
if(strcmp(procname, eglExtensions[ext].name) == 0)
{
return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
}
}
if(rad::getProcAddress != 0)
{
__eglMustCastToProperFunctionPointerType proc = rad::getProcAddress(procname);
if(proc) return proc;
}
}
catch(std::bad_alloc&)
{
return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL);
}
if(rad::getProcAddress != 0)
{
__eglMustCastToProperFunctionPointerType proc = rad::getProcAddress(procname);
if(proc) return proc;
}
return NULL;
}
......
LIBRARY libEGL
EXPORTS
eglBindAPI @14
eglBindTexImage @20
eglChooseConfig @7
eglCopyBuffers @33
eglCreateContext @23
......@@ -25,7 +24,6 @@ EXPORTS
eglQueryContext @29
eglQueryString @5
eglQuerySurface @13
eglReleaseTexImage @21
eglReleaseThread @17
eglSurfaceAttrib @19
eglSwapBuffers @32
......
......@@ -17,7 +17,6 @@
#include "main.h"
#include "mathutil.h"
#include "utilities.h"
#include "ResourceManager.h"
#include "Buffer.h"
#include "Fence.h"
#include "Framebuffer.h"
......@@ -39,11 +38,10 @@
namespace es2
{
Device *Context::device = 0;
Context::Context(const egl::Config *config, const Context *shareContext) : mConfig(config)
{
device = getDevice();
sw::Context *context = new sw::Context();
device = new es2::Device(context);
mFenceHandleAllocator.setBaseHandle(0);
......@@ -115,39 +113,17 @@ Context::Context(const egl::Config *config, const Context *shareContext) : mConf
mState.colorMaskAlpha = true;
mState.depthMask = true;
if(shareContext != NULL)
{
mResourceManager = shareContext->mResourceManager;
mResourceManager->addRef();
}
else
{
mResourceManager = new ResourceManager();
}
// [OpenGL ES 2.0.24] section 3.7 page 83:
// In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
// and cube map texture state vectors respectively associated with them.
// In order that access to these initial textures not be lost, they are treated as texture
// objects all of whose names are 0.
mTexture2DZero.set(new Texture2D(0));
mTextureCubeMapZero.set(new TextureCubeMap(0));
mTextureExternalZero.set(new TextureExternal(0));
mState.activeSampler = 0;
mState.elementArrayBuffer = 0;
bindTextureCubeMap(0);
bindTexture2D(0);
bindReadFramebuffer(0);
bindDrawFramebuffer(0);
bindRenderbuffer(0);
mState.currentProgram = 0;
mState.packAlignment = 4;
mState.unpackAlignment = 4;
mState.program = 0;
mState.colorBuffer = 0;
mState.depthBuffer = 0;
mState.stencilBuffer = 0;
mVertexDataManager = NULL;
mIndexDataManager = NULL;
......@@ -164,61 +140,8 @@ Context::Context(const egl::Config *config, const Context *shareContext) : mConf
Context::~Context()
{
if(mState.currentProgram != 0)
{
Program *programObject = mResourceManager->getProgram(mState.currentProgram);
if(programObject)
{
programObject->release();
}
mState.currentProgram = 0;
}
while(!mFramebufferMap.empty())
{
deleteFramebuffer(mFramebufferMap.begin()->first);
}
while(!mFenceMap.empty())
{
deleteFence(mFenceMap.begin()->first);
}
while(!mQueryMap.empty())
{
deleteQuery(mQueryMap.begin()->first);
}
for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
{
mState.samplerTexture[type][sampler].set(NULL);
}
}
for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
mState.vertexAttribute[i].buffer = 0;
}
for(int i = 0; i < QUERY_TYPE_COUNT; i++)
{
mState.activeQuery[i].set(NULL);
}
//mState.arrayBuffer.set(NULL);
//mState.elementArrayBuffer.set(NULL);
//mState.renderbuffer.set(NULL);
mTexture2DZero.set(NULL);
mTextureCubeMapZero.set(NULL);
mTextureExternalZero.set(NULL);
delete mVertexDataManager;
delete mIndexDataManager;
mResourceManager->release();
}
void Context::makeCurrent(egl::Surface *surface)
......@@ -240,26 +163,6 @@ void Context::makeCurrent(egl::Surface *surface)
mHasBeenCurrent = true;
}
// Wrap the existing resources into GL objects and assign them to the '0' names
egl::Image *defaultRenderTarget = surface->getRenderTarget();
egl::Image *depthStencil = surface->getDepthStencil();
Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
setFramebufferZero(framebufferZero);
if(defaultRenderTarget)
{
defaultRenderTarget->release();
}
if(depthStencil)
{
depthStencil->release();
}
markAllStateDirty();
}
......@@ -648,21 +551,6 @@ void Context::setActiveSampler(unsigned int active)
mState.activeSampler = active;
}
GLuint Context::getReadFramebufferHandle() const
{
return mState.readFramebuffer;
}
GLuint Context::getDrawFramebufferHandle() const
{
return mState.drawFramebuffer;
}
GLuint Context::getRenderbufferHandle() const
{
return mState.renderbuffer.id();
}
GLuint Context::getActiveQuery(GLenum target) const
{
Query *queryObject = NULL;
......@@ -733,589 +621,179 @@ GLint Context::getUnpackAlignment() const
return mState.unpackAlignment;
}
GLuint Context::createProgram()
{
return mResourceManager->createProgram();
}
GLuint Context::createShader(GLenum type)
{
return mResourceManager->createShader(type);
}
GLuint Context::createTexture()
{
return mResourceManager->createTexture();
}
GLuint Context::createRenderbuffer()
{
return mResourceManager->createRenderbuffer();
}
// Returns an unused framebuffer name
GLuint Context::createFramebuffer()
{
GLuint handle = mFramebufferHandleAllocator.allocate();
mFramebufferMap[handle] = NULL;
return handle;
}
GLuint Context::createFence()
void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
{
GLuint handle = mFenceHandleAllocator.allocate();
mFenceMap[handle] = new Fence;
return handle;
Renderbuffer *renderbufferObject = mState.renderbuffer.get();
renderbufferObject->setStorage(renderbuffer);
}
// Returns an unused query name
GLuint Context::createQuery()
// Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle
bool Context::applyRenderTarget()
{
GLuint handle = mQueryHandleAllocator.allocate();
egl::Image *renderTarget = mState.colorBuffer;//framebuffer->getRenderTarget();
device->setRenderTarget(renderTarget);
//if(renderTarget) renderTarget->release();
mQueryMap[handle] = NULL;
egl::Image *depthStencil = mState.depthBuffer;//framebuffer->getDepthStencil();
device->setDepthStencilSurface(depthStencil);
//if(depthStencil) depthStencil->release();
return handle;
}
Viewport viewport;
float zNear = clamp01(mState.zNear);
float zFar = clamp01(mState.zFar);
void Context::deleteShader(GLuint shader)
{
mResourceManager->deleteShader(shader);
}
viewport.x0 = mState.viewportX;
viewport.y0 = mState.viewportY;
viewport.width = mState.viewportWidth;
viewport.height = mState.viewportHeight;
viewport.minZ = zNear;
viewport.maxZ = zFar;
void Context::deleteProgram(GLuint program)
{
mResourceManager->deleteProgram(program);
}
device->setViewport(viewport);
void Context::deleteTexture(GLuint texture)
{
if(mResourceManager->getTexture(texture))
if(mState.scissorTest)
{
detachTexture(texture);
sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight};
scissor.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
device->setScissorRect(scissor);
device->setScissorEnable(true);
}
mResourceManager->deleteTexture(texture);
}
void Context::deleteRenderbuffer(GLuint renderbuffer)
{
if(mResourceManager->getRenderbuffer(renderbuffer))
else
{
detachRenderbuffer(renderbuffer);
device->setScissorEnable(false);
}
mResourceManager->deleteRenderbuffer(renderbuffer);
}
void Context::deleteFramebuffer(GLuint framebuffer)
{
FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
if(framebufferObject != mFramebufferMap.end())
{
detachFramebuffer(framebuffer);
Program *program = mState.program;
mFramebufferHandleAllocator.release(framebufferObject->first);
delete framebufferObject->second;
mFramebufferMap.erase(framebufferObject);
if(program)
{
GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
program->setUniform1fv(program->getUniformLocation("gl_DepthRange.near"), 1, &nearFarDiff[0]);
program->setUniform1fv(program->getUniformLocation("gl_DepthRange.far"), 1, &nearFarDiff[1]);
program->setUniform1fv(program->getUniformLocation("gl_DepthRange.diff"), 1, &nearFarDiff[2]);
}
return true;
}
void Context::deleteFence(GLuint fence)
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc)
void Context::applyState(GLenum drawMode)
{
FenceMap::iterator fenceObject = mFenceMap.find(fence);
if(fenceObject != mFenceMap.end())
if(mState.cullFace)
{
mFenceHandleAllocator.release(fenceObject->first);
delete fenceObject->second;
mFenceMap.erase(fenceObject);
device->setCullMode(rad2sw::ConvertCullMode(mState.cullMode, mState.frontFace));
}
else
{
device->setCullMode(sw::CULL_NONE);
}
}
void Context::deleteQuery(GLuint query)
{
QueryMap::iterator queryObject = mQueryMap.find(query);
if(queryObject != mQueryMap.end())
if(mDepthStateDirty)
{
mQueryHandleAllocator.release(queryObject->first);
if(queryObject->second)
if(mState.depthTest)
{
queryObject->second->release();
device->setDepthBufferEnable(true);
device->setDepthCompare(rad2sw::ConvertDepthComparison(mState.depthFunc));
}
else
{
device->setDepthBufferEnable(false);
}
mQueryMap.erase(queryObject);
}
}
Shader *Context::getShader(GLuint handle)
{
return mResourceManager->getShader(handle);
}
mDepthStateDirty = false;
}
Program *Context::getProgram(GLuint handle)
{
return mResourceManager->getProgram(handle);
}
if(mBlendStateDirty)
{
if(mState.blend)
{
device->setAlphaBlendEnable(true);
device->setSeparateAlphaBlendEnable(true);
Texture *Context::getTexture(GLuint handle)
{
return mResourceManager->getTexture(handle);
}
device->setBlendConstant(rad2sw::ConvertColor(mState.blendColor));
Renderbuffer *Context::getRenderbuffer(GLuint handle)
{
return mResourceManager->getRenderbuffer(handle);
}
device->setSourceBlendFactor(rad2sw::ConvertBlendFunc(mState.sourceBlendRGB));
device->setDestBlendFactor(rad2sw::ConvertBlendFunc(mState.destBlendRGB));
device->setBlendOperation(rad2sw::ConvertBlendOp(mState.blendEquationRGB));
Framebuffer *Context::getReadFramebuffer()
{
return getFramebuffer(mState.readFramebuffer);
}
device->setSourceBlendFactorAlpha(rad2sw::ConvertBlendFunc(mState.sourceBlendAlpha));
device->setDestBlendFactorAlpha(rad2sw::ConvertBlendFunc(mState.destBlendAlpha));
device->setBlendOperationAlpha(rad2sw::ConvertBlendOp(mState.blendEquationAlpha));
}
else
{
device->setAlphaBlendEnable(false);
}
Framebuffer *Context::getDrawFramebuffer()
{
return getFramebuffer(mState.drawFramebuffer);
}
mBlendStateDirty = false;
}
void Context::bindTexture2D(GLuint texture)
{
mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
if(mStencilStateDirty || mFrontFaceDirty)
{
if(mState.stencilTest && mState.stencilBuffer)
{
device->setStencilEnable(true);
device->setTwoSidedStencil(true);
mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
}
if(mState.stencilWritemask != mState.stencilBackWritemask ||
mState.stencilRef != mState.stencilBackRef ||
mState.stencilMask != mState.stencilBackMask)
{
ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
return error(GL_INVALID_OPERATION);
}
void Context::bindTextureCubeMap(GLuint texture)
{
mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
// get the maximum size of the stencil ref
egl::Image *stencilbuffer = mState.stencilBuffer;
GLuint maxStencil = (1 << sw2rad::GetStencilSize(stencilbuffer->getInternalFormat())) - 1;
mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
}
if(mState.frontFace == GL_CCW)
{
device->setStencilWriteMask(mState.stencilWritemask);
device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilFunc));
void Context::bindTextureExternal(GLuint texture)
{
mResourceManager->checkTextureAllocation(texture, TEXTURE_EXTERNAL);
device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
device->setStencilMask(mState.stencilMask);
mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].set(getTexture(texture));
}
device->setStencilFailOperation(rad2sw::ConvertStencilOp(mState.stencilFail));
device->setStencilZFailOperation(rad2sw::ConvertStencilOp(mState.stencilPassDepthFail));
device->setStencilPassOperation(rad2sw::ConvertStencilOp(mState.stencilPassDepthPass));
void Context::bindReadFramebuffer(GLuint framebuffer)
{
if(!getFramebuffer(framebuffer))
{
mFramebufferMap[framebuffer] = new Framebuffer();
}
device->setStencilWriteMaskCCW(mState.stencilBackWritemask);
device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));
mState.readFramebuffer = framebuffer;
}
device->setStencilReferenceCCW((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
device->setStencilMaskCCW(mState.stencilBackMask);
void Context::bindDrawFramebuffer(GLuint framebuffer)
{
if(!getFramebuffer(framebuffer))
{
mFramebufferMap[framebuffer] = new Framebuffer();
}
device->setStencilFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackFail));
device->setStencilZFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
device->setStencilPassOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
}
else
{
device->setStencilWriteMaskCCW(mState.stencilWritemask);
device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilFunc));
mState.drawFramebuffer = framebuffer;
}
device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
device->setStencilMaskCCW(mState.stencilMask);
void Context::bindRenderbuffer(GLuint renderbuffer)
{
mState.renderbuffer.set(getRenderbuffer(renderbuffer));
}
device->setStencilFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilFail));
device->setStencilZFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilPassDepthFail));
device->setStencilPassOperationCCW(rad2sw::ConvertStencilOp(mState.stencilPassDepthPass));
void Context::useProgram(GLuint program)
{
GLuint priorProgram = mState.currentProgram;
mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
device->setStencilWriteMask(mState.stencilBackWritemask);
device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));
if(priorProgram != program)
{
Program *newProgram = mResourceManager->getProgram(program);
Program *oldProgram = mResourceManager->getProgram(priorProgram);
device->setStencilReference((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
device->setStencilMask(mState.stencilBackMask);
if(newProgram)
{
newProgram->addRef();
device->setStencilFailOperation(rad2sw::ConvertStencilOp(mState.stencilBackFail));
device->setStencilZFailOperation(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
device->setStencilPassOperation(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
}
}
if(oldProgram)
{
oldProgram->release();
}
}
}
void Context::beginQuery(GLenum target, GLuint query)
{
// From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
// of zero, if the active query object name for <target> is non-zero (for the
// targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
// the active query for either target is non-zero), if <id> is the name of an
// existing query object whose type does not match <target>, or if <id> is the
// active query object name for any query type, the error INVALID_OPERATION is
// generated.
// Ensure no other queries are active
// NOTE: If other queries than occlusion are supported, we will need to check
// separately that:
// a) The query ID passed is not the current active query for any target/type
// b) There are no active queries for the requested target (and in the case
// of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
// no query may be active for either if glBeginQuery targets either.
for(int i = 0; i < QUERY_TYPE_COUNT; i++)
{
if(mState.activeQuery[i].get() != NULL)
{
return error(GL_INVALID_OPERATION);
}
}
QueryType qType;
switch(target)
{
case GL_ANY_SAMPLES_PASSED_EXT:
qType = QUERY_ANY_SAMPLES_PASSED;
break;
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
break;
default:
ASSERT(false);
}
Query *queryObject = getQuery(query, true, target);
// Check that name was obtained with glGenQueries
if(!queryObject)
{
return error(GL_INVALID_OPERATION);
}
// Check for type mismatch
if(queryObject->getType() != target)
{
return error(GL_INVALID_OPERATION);
}
// Set query as active for specified target
mState.activeQuery[qType].set(queryObject);
// Begin query
queryObject->begin();
}
void Context::endQuery(GLenum target)
{
QueryType qType;
switch(target)
{
case GL_ANY_SAMPLES_PASSED_EXT:
qType = QUERY_ANY_SAMPLES_PASSED;
break;
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
break;
default:
ASSERT(false);
}
Query *queryObject = mState.activeQuery[qType].get();
if(queryObject == NULL)
{
return error(GL_INVALID_OPERATION);
}
queryObject->end();
mState.activeQuery[qType].set(NULL);
}
void Context::setFramebufferZero(Framebuffer *buffer)
{
delete mFramebufferMap[0];
mFramebufferMap[0] = buffer;
}
void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
{
Renderbuffer *renderbufferObject = mState.renderbuffer.get();
renderbufferObject->setStorage(renderbuffer);
}
Framebuffer *Context::getFramebuffer(unsigned int handle)
{
FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
if(framebuffer == mFramebufferMap.end())
{
return NULL;
}
else
{
return framebuffer->second;
}
}
Fence *Context::getFence(unsigned int handle)
{
FenceMap::iterator fence = mFenceMap.find(handle);
if(fence == mFenceMap.end())
{
return NULL;
}
else
{
return fence->second;
}
}
Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
{
QueryMap::iterator query = mQueryMap.find(handle);
if(query == mQueryMap.end())
{
return NULL;
}
else
{
if(!query->second && create)
{
query->second = new Query(handle, type);
query->second->addRef();
}
return query->second;
}
}
Program *Context::getCurrentProgram()
{
return mState.program;
//return mResourceManager->getProgram(mState.currentProgram);
}
Texture2D *Context::getTexture2D()
{
return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
}
TextureCubeMap *Context::getTextureCubeMap()
{
return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
}
TextureExternal *Context::getTextureExternal()
{
return static_cast<TextureExternal*>(getSamplerTexture(mState.activeSampler, TEXTURE_EXTERNAL));
}
Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
{
GLuint texid = mState.samplerTexture[type][sampler].id();
if(texid == 0) // Special case: 0 refers to different initial textures based on the target
{
switch (type)
{
case TEXTURE_2D: return mTexture2DZero.get();
case TEXTURE_CUBE: return mTextureCubeMapZero.get();
case TEXTURE_EXTERNAL: return mTextureExternalZero.get();
default: UNREACHABLE();
}
}
return mState.samplerTexture[type][sampler].get();
}
// Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle
bool Context::applyRenderTarget()
{
Framebuffer *framebuffer = getDrawFramebuffer();
int width, height, samples;
if(!framebuffer || framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE)
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
}
egl::Image *renderTarget = mState.colorBuffer;//framebuffer->getRenderTarget();
device->setRenderTarget(renderTarget);
//if(renderTarget) renderTarget->release();
egl::Image *depthStencil = mState.depthBuffer;//framebuffer->getDepthStencil();
device->setDepthStencilSurface(depthStencil);
//if(depthStencil) depthStencil->release();
Viewport viewport;
float zNear = clamp01(mState.zNear);
float zFar = clamp01(mState.zFar);
viewport.x0 = mState.viewportX;
viewport.y0 = mState.viewportY;
viewport.width = mState.viewportWidth;
viewport.height = mState.viewportHeight;
viewport.minZ = zNear;
viewport.maxZ = zFar;
device->setViewport(viewport);
if(mState.scissorTest)
{
sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight};
scissor.clip(0, 0, width, height);
device->setScissorRect(scissor);
device->setScissorEnable(true);
}
else
{
device->setScissorEnable(false);
}
Program *program = getCurrentProgram();
if(program)
{
GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
program->setUniform1fv(program->getUniformLocation("gl_DepthRange.near"), 1, &nearFarDiff[0]);
program->setUniform1fv(program->getUniformLocation("gl_DepthRange.far"), 1, &nearFarDiff[1]);
program->setUniform1fv(program->getUniformLocation("gl_DepthRange.diff"), 1, &nearFarDiff[2]);
}
return true;
}
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc)
void Context::applyState(GLenum drawMode)
{
Framebuffer *framebuffer = getDrawFramebuffer();
if(mState.cullFace)
{
device->setCullMode(rad2sw::ConvertCullMode(mState.cullMode, mState.frontFace));
}
else
{
device->setCullMode(sw::CULL_NONE);
}
if(mDepthStateDirty)
{
if(mState.depthTest)
{
device->setDepthBufferEnable(true);
device->setDepthCompare(rad2sw::ConvertDepthComparison(mState.depthFunc));
}
else
{
device->setDepthBufferEnable(false);
}
mDepthStateDirty = false;
}
if(mBlendStateDirty)
{
if(mState.blend)
{
device->setAlphaBlendEnable(true);
device->setSeparateAlphaBlendEnable(true);
device->setBlendConstant(rad2sw::ConvertColor(mState.blendColor));
device->setSourceBlendFactor(rad2sw::ConvertBlendFunc(mState.sourceBlendRGB));
device->setDestBlendFactor(rad2sw::ConvertBlendFunc(mState.destBlendRGB));
device->setBlendOperation(rad2sw::ConvertBlendOp(mState.blendEquationRGB));
device->setSourceBlendFactorAlpha(rad2sw::ConvertBlendFunc(mState.sourceBlendAlpha));
device->setDestBlendFactorAlpha(rad2sw::ConvertBlendFunc(mState.destBlendAlpha));
device->setBlendOperationAlpha(rad2sw::ConvertBlendOp(mState.blendEquationAlpha));
}
else
{
device->setAlphaBlendEnable(false);
}
mBlendStateDirty = false;
}
if(mStencilStateDirty || mFrontFaceDirty)
{
if(mState.stencilTest && framebuffer->hasStencil())
{
device->setStencilEnable(true);
device->setTwoSidedStencil(true);
if(mState.stencilWritemask != mState.stencilBackWritemask ||
mState.stencilRef != mState.stencilBackRef ||
mState.stencilMask != mState.stencilBackMask)
{
ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
return error(GL_INVALID_OPERATION);
}
// get the maximum size of the stencil ref
Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
if(mState.frontFace == GL_CCW)
{
device->setStencilWriteMask(mState.stencilWritemask);
device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilFunc));
device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
device->setStencilMask(mState.stencilMask);
device->setStencilFailOperation(rad2sw::ConvertStencilOp(mState.stencilFail));
device->setStencilZFailOperation(rad2sw::ConvertStencilOp(mState.stencilPassDepthFail));
device->setStencilPassOperation(rad2sw::ConvertStencilOp(mState.stencilPassDepthPass));
device->setStencilWriteMaskCCW(mState.stencilBackWritemask);
device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));
device->setStencilReferenceCCW((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
device->setStencilMaskCCW(mState.stencilBackMask);
device->setStencilFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackFail));
device->setStencilZFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
device->setStencilPassOperationCCW(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
}
else
{
device->setStencilWriteMaskCCW(mState.stencilWritemask);
device->setStencilCompareCCW(rad2sw::ConvertStencilComparison(mState.stencilFunc));
device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
device->setStencilMaskCCW(mState.stencilMask);
device->setStencilFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilFail));
device->setStencilZFailOperationCCW(rad2sw::ConvertStencilOp(mState.stencilPassDepthFail));
device->setStencilPassOperationCCW(rad2sw::ConvertStencilOp(mState.stencilPassDepthPass));
device->setStencilWriteMask(mState.stencilBackWritemask);
device->setStencilCompare(rad2sw::ConvertStencilComparison(mState.stencilBackFunc));
device->setStencilReference((mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
device->setStencilMask(mState.stencilBackMask);
device->setStencilFailOperation(rad2sw::ConvertStencilOp(mState.stencilBackFail));
device->setStencilZFailOperation(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthFail));
device->setStencilPassOperation(rad2sw::ConvertStencilOp(mState.stencilBackPassDepthPass));
}
}
else
else
{
device->setStencilEnable(false);
}
......@@ -1336,11 +814,11 @@ void Context::applyState(GLenum drawMode)
{
if(mState.polygonOffsetFill)
{
Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
egl::Image *depthbuffer = mState.depthBuffer;
if(depthbuffer)
{
device->setSlopeDepthBias(mState.polygonOffsetFactor);
float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(sw2rad::GetDepthSize(depthbuffer->getInternalFormat())));
device->setDepthBias(depthBias);
}
}
......@@ -1369,8 +847,9 @@ void Context::applyState(GLenum drawMode)
unsigned int mask = 0;
if(mState.sampleCoverageValue != 0)
{
int width, height, samples;
framebuffer->completeness(width, height, samples);
int width = mState.colorBuffer->getWidth();
int height = mState.colorBuffer->getHeight();
int samples = mState.colorBuffer->getMultiSampleDepth();
float threshold = 0.5f;
......@@ -1419,7 +898,7 @@ GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count)
return err;
}
Program *program = getCurrentProgram();
Program *program = mState.program;
device->resetInputStreams(false);
......@@ -1466,7 +945,7 @@ GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode
// Applies the shaders and shader constants
void Context::applyShaders()
{
Program *programObject = getCurrentProgram();
Program *programObject = mState.program;
sw::VertexShader *vertexShader = programObject->getVertexShader();
sw::PixelShader *pixelShader = programObject->getPixelShader();
......@@ -1482,66 +961,9 @@ void Context::applyShaders()
programObject->applyUniforms();
}
void Context::applyTextures()
{
applyTextures(sw::SAMPLER_PIXEL);
applyTextures(sw::SAMPLER_VERTEX);
}
void Context::applyTextures(sw::SamplerType samplerType)
{
Program *programObject = getCurrentProgram();
int samplerCount = (samplerType == sw::SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS; // Range of samplers of given sampler type
for(int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)
{
int textureUnit = programObject->getSamplerMapping(samplerType, samplerIndex); // OpenGL texture image unit index
if(textureUnit != -1)
{
TextureType textureType = programObject->getSamplerTextureType(samplerType, samplerIndex);
Texture *texture = getSamplerTexture(textureUnit, textureType);
if(texture->isSamplerComplete())
{
GLenum wrapS = texture->getWrapS();
GLenum wrapT = texture->getWrapT();
GLenum texFilter = texture->getMinFilter();
GLenum magFilter = texture->getMagFilter();
GLfloat maxAnisotropy = texture->getMaxAnisotropy();
device->setAddressingModeU(samplerType, samplerIndex, rad2sw::ConvertTextureWrap(wrapS));
device->setAddressingModeV(samplerType, samplerIndex, rad2sw::ConvertTextureWrap(wrapT));
sw::FilterType minFilter;
sw::MipmapType mipFilter;
rad2sw::ConvertMinFilter(texFilter, &minFilter, &mipFilter, maxAnisotropy);
// ASSERT(minFilter == rad2sw::ConvertMagFilter(magFilter));
device->setTextureFilter(samplerType, samplerIndex, minFilter);
// device->setTextureFilter(samplerType, samplerIndex, rad2sw::ConvertMagFilter(magFilter));
device->setMipmapFilter(samplerType, samplerIndex, mipFilter);
device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy);
applyTexture(samplerType, samplerIndex, texture);
}
else
{
applyTexture(samplerType, samplerIndex, 0);
}
}
else
{
applyTexture(samplerType, samplerIndex, NULL);
}
}
}
void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture)
{
//Program *program = getCurrentProgram();
//Program *program = mState.program;
int sampler = (type == sw::SAMPLER_PIXEL) ? index : 16 + index;
bool textureUsed = true;
......@@ -1624,286 +1046,25 @@ void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture
}
else if(surfaceLevel >= levelCount)
{
surfaceLevel = levelCount - 1;
}
egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
}
}
}
else UNIMPLEMENTED();
}
else
{
device->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);
}
}
void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
{
Framebuffer *framebuffer = getReadFramebuffer();
int framebufferWidth, framebufferHeight, framebufferSamples;
if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE)
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
}
if(getReadFramebufferHandle() != 0 && framebufferSamples != 0)
{
return error(GL_INVALID_OPERATION);
}
GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
// Sized query sanity check
if(bufSize)
{
int requiredSize = outputPitch * height;
if(requiredSize > *bufSize)
{
return error(GL_INVALID_OPERATION);
}
}
egl::Image *renderTarget = framebuffer->getRenderTarget();
if(!renderTarget)
{
return error(GL_OUT_OF_MEMORY);
}
sw::Rect rect = {x, y, x + width, y + height};
rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY);
unsigned char *dest = (unsigned char*)pixels;
unsigned short *dest16 = (unsigned short*)pixels;
int inputPitch = (int)renderTarget->getPitch();
for(int j = 0; j < rect.y1 - rect.y0; j++)
{
if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 &&
format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
{
// Fast path for EXT_read_format_bgra, given an RGBA source buffer
// Note that buffers with no alpha go through the slow path below
memcpy(dest + j * outputPitch, source + j * inputPitch, (rect.x1 - rect.x0) * 4);
}
else
{
for(int i = 0; i < rect.x1 - rect.x0; i++)
{
float r;
float g;
float b;
float a;
switch(renderTarget->getInternalFormat())
{
case sw::FORMAT_R5G6B5:
{
unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
a = 1.0f;
b = (rgb & 0x001F) * (1.0f / 0x001F);
g = (rgb & 0x07E0) * (1.0f / 0x07E0);
r = (rgb & 0xF800) * (1.0f / 0xF800);
}
break;
case sw::FORMAT_A1R5G5B5:
{
unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
a = (argb & 0x8000) ? 1.0f : 0.0f;
b = (argb & 0x001F) * (1.0f / 0x001F);
g = (argb & 0x03E0) * (1.0f / 0x03E0);
r = (argb & 0x7C00) * (1.0f / 0x7C00);
}
break;
case sw::FORMAT_A8R8G8B8:
{
unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
}
break;
case sw::FORMAT_X8R8G8B8:
{
unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
a = 1.0f;
b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
}
break;
case sw::FORMAT_A2R10G10B10:
{
unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
}
break;
case sw::FORMAT_A32B32G32R32F:
{
r = *((float*)(source + 16 * i + j * inputPitch) + 0);
g = *((float*)(source + 16 * i + j * inputPitch) + 1);
b = *((float*)(source + 16 * i + j * inputPitch) + 2);
a = *((float*)(source + 16 * i + j * inputPitch) + 3);
}
break;
case sw::FORMAT_A16B16G16R16F:
{
r = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 0);
g = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 1);
b = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 2);
a = (float)*((sw::half*)(source + 8 * i + j * inputPitch) + 3);
}
break;
default:
UNIMPLEMENTED(); // FIXME
UNREACHABLE();
}
switch(format)
{
case GL_RGBA:
switch(type)
{
case GL_UNSIGNED_BYTE:
dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
break;
default: UNREACHABLE();
}
break;
case GL_BGRA_EXT:
switch(type)
{
case GL_UNSIGNED_BYTE:
dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
// According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
// this type is packed as follows:
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// --------------------------------------------------------------------------------
// | 4th | 3rd | 2nd | 1st component |
// --------------------------------------------------------------------------------
// in the case of BGRA_EXT, B is the first component, G the second, and so forth.
dest16[i + j * outputPitch / sizeof(unsigned short)] =
((unsigned short)(15 * a + 0.5f) << 12)|
((unsigned short)(15 * r + 0.5f) << 8) |
((unsigned short)(15 * g + 0.5f) << 4) |
((unsigned short)(15 * b + 0.5f) << 0);
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
// According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
// this type is packed as follows:
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// --------------------------------------------------------------------------------
// | 4th | 3rd | 2nd | 1st component |
// --------------------------------------------------------------------------------
// in the case of BGRA_EXT, B is the first component, G the second, and so forth.
dest16[i + j * outputPitch / sizeof(unsigned short)] =
((unsigned short)( a + 0.5f) << 15) |
((unsigned short)(31 * r + 0.5f) << 10) |
((unsigned short)(31 * g + 0.5f) << 5) |
((unsigned short)(31 * b + 0.5f) << 0);
break;
default: UNREACHABLE();
}
break;
case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
switch(type)
{
case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
dest16[i + j * outputPitch / sizeof(unsigned short)] =
((unsigned short)(31 * b + 0.5f) << 0) |
((unsigned short)(63 * g + 0.5f) << 5) |
((unsigned short)(31 * r + 0.5f) << 11);
break;
default: UNREACHABLE();
surfaceLevel = levelCount - 1;
}
break;
default: UNREACHABLE();
egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
}
}
}
}
renderTarget->unlock();
renderTarget->release();
}
void Context::clear(GLbitfield mask)
{
Framebuffer *framebuffer = getDrawFramebuffer();
if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
}
if(!applyRenderTarget())
{
return;
}
unsigned int color = (unorm<8>(mState.colorClearValue.alpha) << 24) |
(unorm<8>(mState.colorClearValue.red) << 16) |
(unorm<8>(mState.colorClearValue.green) << 8) |
(unorm<8>(mState.colorClearValue.blue) << 0);
float depth = clamp01(mState.depthClearValue);
int stencil = mState.stencilClearValue & 0x000000FF;
if(mask & GL_COLOR_BUFFER_BIT)
{
unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) |
(mState.colorMaskGreen ? 0x2 : 0) |
(mState.colorMaskBlue ? 0x4 : 0) |
(mState.colorMaskAlpha ? 0x8 : 0);
if(rgbaMask != 0)
{
device->clearColor(color, rgbaMask);
}
}
if(mask & GL_DEPTH_BUFFER_BIT)
{
if(mState.depthMask != 0)
{
device->clearDepth(depth);
}
else UNIMPLEMENTED();
}
if(mask & GL_STENCIL_BUFFER_BIT)
else
{
if(mState.stencilWritemask != 0)
{
device->clearStencil(stencil, mState.stencilWritemask);
}
device->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);
}
}
void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
{
if(!mState.currentProgram)
if(!mState.program)
{
return error(GL_INVALID_OPERATION);
}
......@@ -1933,9 +1094,8 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
}
applyShaders();
applyTextures();
if(!getCurrentProgram()->validateSamplers(false))
if(!mState.program->validateSamplers(false))
{
return error(GL_INVALID_OPERATION);
}
......@@ -1948,7 +1108,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
{
if(!mState.currentProgram && !mState.program)
if(!mState.program)
{
return error(GL_INVALID_OPERATION);
}
......@@ -1993,7 +1153,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
applyShaders();
//applyTextures();
if(!getCurrentProgram()->validateSamplers(false))
if(!mState.program->validateSamplers(false))
{
return error(GL_INVALID_OPERATION);
}
......@@ -2096,89 +1256,6 @@ int Context::getSupportedMultiSampleDepth(sw::Format format, int requested)
return 4;
}
void Context::detachTexture(GLuint texture)
{
// [OpenGL ES 2.0.24] section 3.8 page 84:
// If a texture object is deleted, it is as if all texture units which are bound to that texture object are
// rebound to texture object zero
for(int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
for(int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
{
if(mState.samplerTexture[type][sampler].id() == texture)
{
mState.samplerTexture[type][sampler].set(NULL);
}
}
}
// [OpenGL ES 2.0.24] section 4.4 page 112:
// If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
// as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
// image was attached in the currently bound framebuffer.
Framebuffer *readFramebuffer = getReadFramebuffer();
Framebuffer *drawFramebuffer = getDrawFramebuffer();
if(readFramebuffer)
{
readFramebuffer->detachTexture(texture);
}
if(drawFramebuffer && drawFramebuffer != readFramebuffer)
{
drawFramebuffer->detachTexture(texture);
}
}
void Context::detachFramebuffer(GLuint framebuffer)
{
// [OpenGL ES 2.0.24] section 4.4 page 107:
// If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
// BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
if(mState.readFramebuffer == framebuffer)
{
bindReadFramebuffer(0);
}
if(mState.drawFramebuffer == framebuffer)
{
bindDrawFramebuffer(0);
}
}
void Context::detachRenderbuffer(GLuint renderbuffer)
{
// [OpenGL ES 2.0.24] section 4.4 page 109:
// If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
// had been executed with the target RENDERBUFFER and name of zero.
if(mState.renderbuffer.id() == renderbuffer)
{
bindRenderbuffer(0);
}
// [OpenGL ES 2.0.24] section 4.4 page 111:
// If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
// then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
// point to which this image was attached in the currently bound framebuffer.
Framebuffer *readFramebuffer = getReadFramebuffer();
Framebuffer *drawFramebuffer = getDrawFramebuffer();
if(readFramebuffer)
{
readFramebuffer->detachRenderbuffer(renderbuffer);
}
if(drawFramebuffer && drawFramebuffer != readFramebuffer)
{
drawFramebuffer->detachRenderbuffer(renderbuffer);
}
}
bool Context::cullSkipsDraw(GLenum drawMode)
{
return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
......@@ -2203,396 +1280,8 @@ bool Context::isTriangleMode(GLenum drawMode)
return false;
}
void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask)
{
Framebuffer *readFramebuffer = getReadFramebuffer();
Framebuffer *drawFramebuffer = getDrawFramebuffer();
int readBufferWidth, readBufferHeight, readBufferSamples;
int drawBufferWidth, drawBufferHeight, drawBufferSamples;
if(!readFramebuffer || readFramebuffer->completeness(readBufferWidth, readBufferHeight, readBufferSamples) != GL_FRAMEBUFFER_COMPLETE ||
!drawFramebuffer || drawFramebuffer->completeness(drawBufferWidth, drawBufferHeight, drawBufferSamples) != GL_FRAMEBUFFER_COMPLETE)
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
}
if(drawBufferSamples > 1)
{
return error(GL_INVALID_OPERATION);
}
sw::Rect sourceRect;
sw::Rect destRect;
if(srcX0 < srcX1)
{
sourceRect.x0 = srcX0;
sourceRect.x1 = srcX1;
destRect.x0 = dstX0;
destRect.x1 = dstX1;
}
else
{
sourceRect.x0 = srcX1;
destRect.x0 = dstX1;
sourceRect.x1 = srcX0;
destRect.x1 = dstX0;
}
if(srcY0 < srcY1)
{
sourceRect.y0 = srcY0;
destRect.y0 = dstY0;
sourceRect.y1 = srcY1;
destRect.y1 = dstY1;
}
else
{
sourceRect.y0 = srcY1;
destRect.y0 = dstY1;
sourceRect.y1 = srcY0;
destRect.y1 = dstY0;
}
sw::Rect sourceScissoredRect = sourceRect;
sw::Rect destScissoredRect = destRect;
if(mState.scissorTest) // Only write to parts of the destination framebuffer which pass the scissor test
{
if(destRect.x0 < mState.scissorX)
{
int xDiff = mState.scissorX - destRect.x0;
destScissoredRect.x0 = mState.scissorX;
sourceScissoredRect.x0 += xDiff;
}
if(destRect.x1 > mState.scissorX + mState.scissorWidth)
{
int xDiff = destRect.x1 - (mState.scissorX + mState.scissorWidth);
destScissoredRect.x1 = mState.scissorX + mState.scissorWidth;
sourceScissoredRect.x1 -= xDiff;
}
if(destRect.y0 < mState.scissorY)
{
int yDiff = mState.scissorY - destRect.y0;
destScissoredRect.y0 = mState.scissorY;
sourceScissoredRect.y0 += yDiff;
}
if(destRect.y1 > mState.scissorY + mState.scissorHeight)
{
int yDiff = destRect.y1 - (mState.scissorY + mState.scissorHeight);
destScissoredRect.y1 = mState.scissorY + mState.scissorHeight;
sourceScissoredRect.y1 -= yDiff;
}
}
sw::Rect sourceTrimmedRect = sourceScissoredRect;
sw::Rect destTrimmedRect = destScissoredRect;
// The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
// the actual draw and read surfaces.
if(sourceTrimmedRect.x0 < 0)
{
int xDiff = 0 - sourceTrimmedRect.x0;
sourceTrimmedRect.x0 = 0;
destTrimmedRect.x0 += xDiff;
}
if(sourceTrimmedRect.x1 > readBufferWidth)
{
int xDiff = sourceTrimmedRect.x1 - readBufferWidth;
sourceTrimmedRect.x1 = readBufferWidth;
destTrimmedRect.x1 -= xDiff;
}
if(sourceTrimmedRect.y0 < 0)
{
int yDiff = 0 - sourceTrimmedRect.y0;
sourceTrimmedRect.y0 = 0;
destTrimmedRect.y0 += yDiff;
}
if(sourceTrimmedRect.y1 > readBufferHeight)
{
int yDiff = sourceTrimmedRect.y1 - readBufferHeight;
sourceTrimmedRect.y1 = readBufferHeight;
destTrimmedRect.y1 -= yDiff;
}
if(destTrimmedRect.x0 < 0)
{
int xDiff = 0 - destTrimmedRect.x0;
destTrimmedRect.x0 = 0;
sourceTrimmedRect.x0 += xDiff;
}
if(destTrimmedRect.x1 > drawBufferWidth)
{
int xDiff = destTrimmedRect.x1 - drawBufferWidth;
destTrimmedRect.x1 = drawBufferWidth;
sourceTrimmedRect.x1 -= xDiff;
}
if(destTrimmedRect.y0 < 0)
{
int yDiff = 0 - destTrimmedRect.y0;
destTrimmedRect.y0 = 0;
sourceTrimmedRect.y0 += yDiff;
}
if(destTrimmedRect.y1 > drawBufferHeight)
{
int yDiff = destTrimmedRect.y1 - drawBufferHeight;
destTrimmedRect.y1 = drawBufferHeight;
sourceTrimmedRect.y1 -= yDiff;
}
bool partialBufferCopy = false;
if(sourceTrimmedRect.y1 - sourceTrimmedRect.y0 < readBufferHeight ||
sourceTrimmedRect.x1 - sourceTrimmedRect.x0 < readBufferWidth ||
destTrimmedRect.y1 - destTrimmedRect.y0 < drawBufferHeight ||
destTrimmedRect.x1 - destTrimmedRect.x0 < drawBufferWidth ||
sourceTrimmedRect.y0 != 0 || destTrimmedRect.y0 != 0 || sourceTrimmedRect.x0 != 0 || destTrimmedRect.x0 != 0)
{
partialBufferCopy = true;
}
bool blitRenderTarget = false;
bool blitDepthStencil = false;
if(mask & GL_COLOR_BUFFER_BIT)
{
const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
if(!validReadType || !validDrawType ||
readFramebuffer->getColorbuffer()->getInternalFormat() != drawFramebuffer->getColorbuffer()->getInternalFormat())
{
ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
return error(GL_INVALID_OPERATION);
}
if(partialBufferCopy && readBufferSamples > 1)
{
return error(GL_INVALID_OPERATION);
}
blitRenderTarget = true;
}
if(mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
{
Renderbuffer *readDSBuffer = NULL;
Renderbuffer *drawDSBuffer = NULL;
// We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
// both a depth and stencil buffer, it will be the same buffer.
if(mask & GL_DEPTH_BUFFER_BIT)
{
if(readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
{
if(readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
readFramebuffer->getDepthbuffer()->getInternalFormat() != drawFramebuffer->getDepthbuffer()->getInternalFormat())
{
return error(GL_INVALID_OPERATION);
}
blitDepthStencil = true;
readDSBuffer = readFramebuffer->getDepthbuffer();
drawDSBuffer = drawFramebuffer->getDepthbuffer();
}
}
if(mask & GL_STENCIL_BUFFER_BIT)
{
if(readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
{
if(readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
readFramebuffer->getStencilbuffer()->getInternalFormat() != drawFramebuffer->getStencilbuffer()->getInternalFormat())
{
return error(GL_INVALID_OPERATION);
}
blitDepthStencil = true;
readDSBuffer = readFramebuffer->getStencilbuffer();
drawDSBuffer = drawFramebuffer->getStencilbuffer();
}
}
if(partialBufferCopy)
{
ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
return error(GL_INVALID_OPERATION); // Only whole-buffer copies are permitted
}
if((drawDSBuffer && drawDSBuffer->getSamples() > 1) ||
(readDSBuffer && readDSBuffer->getSamples() > 1))
{
return error(GL_INVALID_OPERATION);
}
}
if(blitRenderTarget || blitDepthStencil)
{
if(blitRenderTarget)
{
egl::Image *readRenderTarget = readFramebuffer->getRenderTarget();
egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget();
bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, false);
readRenderTarget->release();
drawRenderTarget->release();
if(!success)
{
ERR("BlitFramebufferANGLE failed.");
return;
}
}
if(blitDepthStencil)
{
bool success = device->stretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, false);
if(!success)
{
ERR("BlitFramebufferANGLE failed.");
return;
}
}
}
}
void Context::bindTexImage(egl::Surface *surface)
{
es2::Texture2D *textureObject = getTexture2D();
if(textureObject)
{
textureObject->bindTexImage(surface);
}
}
EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel)
{
GLenum textureTarget = GL_NONE;
switch(target)
{
case EGL_GL_TEXTURE_2D_KHR:
textureTarget = GL_TEXTURE_2D;
break;
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
textureTarget = GL_TEXTURE_CUBE_MAP;
break;
case EGL_GL_RENDERBUFFER_KHR:
break;
default:
return EGL_BAD_PARAMETER;
}
if(textureLevel >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
{
return EGL_BAD_MATCH;
}
if(textureTarget != GL_NONE)
{
es2::Texture *texture = getTexture(name);
if(!texture || texture->getTarget() != textureTarget)
{
return EGL_BAD_PARAMETER;
}
if(texture->isShared(textureTarget, textureLevel)) // Bound to an EGLSurface or already an EGLImage sibling
{
return EGL_BAD_ACCESS;
}
if(textureLevel != 0 && !texture->isSamplerComplete())
{
return EGL_BAD_PARAMETER;
}
if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getLevelCount() == 1))
{
return EGL_BAD_PARAMETER;
}
}
else if(target == EGL_GL_RENDERBUFFER_KHR)
{
es2::Renderbuffer *renderbuffer = getRenderbuffer(name);
if(!renderbuffer)
{
return EGL_BAD_PARAMETER;
}
if(renderbuffer->isShared()) // Already an EGLImage sibling
{
return EGL_BAD_ACCESS;
}
}
else UNREACHABLE();
return EGL_SUCCESS;
}
egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textureLevel)
{
GLenum textureTarget = GL_NONE;
switch(target)
{
case EGL_GL_TEXTURE_2D_KHR: textureTarget = GL_TEXTURE_2D; break;
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; break;
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; break;
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; break;
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; break;
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; break;
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: textureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; break;
}
if(textureTarget != GL_NONE)
{
es2::Texture *texture = getTexture(name);
return texture->createSharedImage(textureTarget, textureLevel);
}
else if(target == EGL_GL_RENDERBUFFER_KHR)
{
es2::Renderbuffer *renderbuffer = getRenderbuffer(name);
return renderbuffer->createSharedImage();
}
else UNREACHABLE();
return 0;
}
Device *Context::getDevice()
{
if(!device)
{
sw::Context *context = new sw::Context();
device = new es2::Device(context);
}
return device;
}
......
......@@ -16,7 +16,6 @@
#define LIBGLESV2_CONTEXT_H_
#include "libEGL/Context.hpp"
#include "ResourceManager.h"
#include "HandleAllocator.h"
#include "RefCountObject.h"
#include "Image.hpp"
......@@ -216,15 +215,14 @@ struct State
GLuint readFramebuffer;
GLuint drawFramebuffer;
BindingPointer<Renderbuffer> renderbuffer;
GLuint currentProgram;
Program *program;
egl::Image *colorBuffer;
egl::Image *depthBuffer;
egl::Image *stencilBuffer;
VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS];
BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
GLint unpackAlignment;
GLint packAlignment;
......@@ -300,10 +298,6 @@ public:
void setActiveSampler(unsigned int active);
GLuint getReadFramebufferHandle() const;
GLuint getDrawFramebufferHandle() const;
GLuint getRenderbufferHandle() const;
GLuint getActiveQuery(GLenum target) const;
void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
......@@ -318,64 +312,9 @@ public:
void setPackAlignment(GLint alignment);
GLint getPackAlignment() const;
// These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types
GLuint createShader(GLenum type);
GLuint createProgram();
GLuint createTexture();
GLuint createRenderbuffer();
void deleteShader(GLuint shader);
void deleteProgram(GLuint program);
void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer);
// Framebuffers are owned by the Context, so these methods do not pass through
GLuint createFramebuffer();
void deleteFramebuffer(GLuint framebuffer);
// Fences are owned by the Context
GLuint createFence();
void deleteFence(GLuint fence);
// Queries are owned by the Context
GLuint createQuery();
void deleteQuery(GLuint query);
void bindTexture2D(GLuint texture);
void bindTextureCubeMap(GLuint texture);
void bindTextureExternal(GLuint texture);
void bindReadFramebuffer(GLuint framebuffer);
void bindDrawFramebuffer(GLuint framebuffer);
void bindRenderbuffer(GLuint renderbuffer);
void useProgram(GLuint program);
void beginQuery(GLenum target, GLuint query);
void endQuery(GLenum target);
void setFramebufferZero(Framebuffer *framebuffer);
void setRenderbufferStorage(RenderbufferStorage *renderbuffer);
Fence *getFence(GLuint handle);
Shader *getShader(GLuint handle);
Program *getProgram(GLuint handle);
virtual Texture *getTexture(GLuint handle);
Framebuffer *getFramebuffer(GLuint handle);
virtual Renderbuffer *getRenderbuffer(GLuint handle);
Query *getQuery(GLuint handle, bool create, GLenum type);
Program *getCurrentProgram();
Texture2D *getTexture2D();
TextureCubeMap *getTextureCubeMap();
TextureExternal *getTextureExternal();
Texture *getSamplerTexture(unsigned int sampler, TextureType type);
Framebuffer *getReadFramebuffer();
Framebuffer *getDrawFramebuffer();
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
void clear(GLbitfield mask);
void drawArrays(GLenum mode, GLint first, GLsizei count);
void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
void finish();
......@@ -390,15 +329,7 @@ public:
GLenum getError();
static int getSupportedMultiSampleDepth(sw::Format format, int requested);
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask);
virtual void bindTexImage(egl::Surface *surface);
virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel);
virtual egl::Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel);
Device *getDevice();
public:
......@@ -409,14 +340,8 @@ public:
GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count);
GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
void applyShaders();
void applyTextures();
void applyTextures(sw::SamplerType type);
void applyTexture(sw::SamplerType type, int sampler, Texture *texture);
void detachTexture(GLuint texture);
void detachFramebuffer(GLuint framebuffer);
void detachRenderbuffer(GLuint renderbuffer);
bool cullSkipsDraw(GLenum drawMode);
bool isTriangleMode(GLenum drawMode);
......@@ -424,10 +349,6 @@ public:
State mState;
BindingPointer<Texture2D> mTexture2DZero;
BindingPointer<TextureCubeMap> mTextureCubeMapZero;
BindingPointer<TextureExternal> mTextureExternalZero;
typedef std::map<GLint, Framebuffer*> FramebufferMap;
FramebufferMap mFramebufferMap;
HandleAllocator mFramebufferHandleAllocator;
......@@ -464,10 +385,8 @@ public:
bool mSampleStateDirty;
bool mFrontFaceDirty;
bool mDitherStateDirty;
ResourceManager *mResourceManager;
static Device *device;
Device *device;
};
}
......
......@@ -47,11 +47,11 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
}
else if(type == GL_RENDERBUFFER)
{
buffer = context->getRenderbuffer(handle);
//buffer = context->getRenderbuffer(handle);
}
else if(IsTextureTarget(type))
{
buffer = context->getTexture(handle)->getRenderbuffer(type);
//buffer = context->getTexture(handle)->getRenderbuffer(type);
}
else
{
......
......@@ -53,7 +53,7 @@ namespace es2
{
if(parentTexture)
{
parentTexture->addRef();
return parentTexture->addRef();
}
sw::atomicIncrement(&referenceCount);
......@@ -63,7 +63,7 @@ namespace es2
{
if(parentTexture)
{
parentTexture->release();
return parentTexture->release();
}
if(referenceCount > 0)
......
......@@ -70,7 +70,7 @@ namespace es2
{
}
Program::Program(ResourceManager *manager, GLuint handle) : resourceManager(manager), handle(handle), serial(issueSerial())
Program::Program(GLuint handle) : handle(handle), serial(issueSerial())
{
device = getDevice();
......@@ -1965,9 +1965,9 @@ namespace es2
{
referenceCount--;
if(referenceCount == 0 && orphaned)
if(referenceCount == 0)
{
resourceManager->deleteProgram(handle);
delete this;
}
}
......
......@@ -27,7 +27,6 @@
namespace es2
{
class Device;
class ResourceManager;
class FragmentShader;
class VertexShader;
......@@ -64,10 +63,20 @@ namespace es2
unsigned int index;
};
enum TextureType
{
TEXTURE_2D,
TEXTURE_CUBE,
TEXTURE_EXTERNAL,
TEXTURE_TYPE_COUNT,
TEXTURE_UNKNOWN
};
class Program
{
public:
Program(ResourceManager *manager, GLuint handle);
Program(GLuint handle);
~Program();
......@@ -199,7 +208,6 @@ namespace es2
static unsigned int currentSerial;
ResourceManager *resourceManager;
const GLuint handle;
};
}
......
// SwiftShader Software Renderer
//
// Copyright(c) 2005-2012 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//
// ResourceManager.cpp: Implements the ResourceManager class, which tracks and
// retrieves objects which may be shared by multiple Contexts.
#include "ResourceManager.h"
#include "Buffer.h"
#include "Program.h"
#include "Renderbuffer.h"
#include "Shader.h"
#include "Texture.h"
namespace es2
{
ResourceManager::ResourceManager()
{
mRefCount = 1;
}
ResourceManager::~ResourceManager()
{
while(!mProgramMap.empty())
{
deleteProgram(mProgramMap.begin()->first);
}
while(!mShaderMap.empty())
{
deleteShader(mShaderMap.begin()->first);
}
while(!mRenderbufferMap.empty())
{
deleteRenderbuffer(mRenderbufferMap.begin()->first);
}
while(!mTextureMap.empty())
{
deleteTexture(mTextureMap.begin()->first);
}
}
void ResourceManager::addRef()
{
mRefCount++;
}
void ResourceManager::release()
{
if(--mRefCount == 0)
{
delete this;
}
}
// Returns an unused shader/program name
GLuint ResourceManager::createShader(GLenum type)
{
GLuint handle = mProgramShaderHandleAllocator.allocate();
if(type == GL_VERTEX_SHADER)
{
mShaderMap[handle] = new VertexShader(this, handle);
}
else if(type == GL_FRAGMENT_SHADER)
{
mShaderMap[handle] = new FragmentShader(this, handle);
}
else UNREACHABLE();
return handle;
}
// Returns an unused program/shader name
GLuint ResourceManager::createProgram()
{
GLuint handle = mProgramShaderHandleAllocator.allocate();
mProgramMap[handle] = new Program(this, handle);
return handle;
}
// Returns an unused texture name
GLuint ResourceManager::createTexture()
{
GLuint handle = mTextureHandleAllocator.allocate();
mTextureMap[handle] = NULL;
return handle;
}
// Returns an unused renderbuffer name
GLuint ResourceManager::createRenderbuffer()
{
GLuint handle = mRenderbufferHandleAllocator.allocate();
mRenderbufferMap[handle] = NULL;
return handle;
}
void ResourceManager::deleteShader(GLuint shader)
{
ShaderMap::iterator shaderObject = mShaderMap.find(shader);
if(shaderObject != mShaderMap.end())
{
if(shaderObject->second->getRefCount() == 0)
{
mProgramShaderHandleAllocator.release(shaderObject->first);
delete shaderObject->second;
mShaderMap.erase(shaderObject);
}
else
{
shaderObject->second->flagForDeletion();
}
}
}
void ResourceManager::deleteProgram(GLuint program)
{
ProgramMap::iterator programObject = mProgramMap.find(program);
if(programObject != mProgramMap.end())
{
if(programObject->second->getRefCount() == 0)
{
mProgramShaderHandleAllocator.release(programObject->first);
delete programObject->second;
mProgramMap.erase(programObject);
}
else
{
programObject->second->flagForDeletion();
}
}
}
void ResourceManager::deleteTexture(GLuint texture)
{
TextureMap::iterator textureObject = mTextureMap.find(texture);
if(textureObject != mTextureMap.end())
{
mTextureHandleAllocator.release(textureObject->first);
if(textureObject->second) textureObject->second->release();
mTextureMap.erase(textureObject);
}
}
void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
{
RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
if(renderbufferObject != mRenderbufferMap.end())
{
mRenderbufferHandleAllocator.release(renderbufferObject->first);
if(renderbufferObject->second) renderbufferObject->second->release();
mRenderbufferMap.erase(renderbufferObject);
}
}
Shader *ResourceManager::getShader(unsigned int handle)
{
ShaderMap::iterator shader = mShaderMap.find(handle);
if(shader == mShaderMap.end())
{
return NULL;
}
else
{
return shader->second;
}
}
Texture *ResourceManager::getTexture(unsigned int handle)
{
if(handle == 0) return NULL;
TextureMap::iterator texture = mTextureMap.find(handle);
if(texture == mTextureMap.end())
{
return NULL;
}
else
{
return texture->second;
}
}
Program *ResourceManager::getProgram(unsigned int handle)
{
ProgramMap::iterator program = mProgramMap.find(handle);
if(program == mProgramMap.end())
{
return NULL;
}
else
{
return program->second;
}
}
Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
{
RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
if(renderbuffer == mRenderbufferMap.end())
{
return NULL;
}
else
{
if (!renderbuffer->second)
{
Renderbuffer *renderbufferObject = new Renderbuffer(handle, new Colorbuffer(0, 0, GL_RGBA4_OES, 0));
mRenderbufferMap[handle] = renderbufferObject;
renderbufferObject->addRef();
}
return renderbuffer->second;
}
}
void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
{
mRenderbufferMap[handle] = buffer;
}
void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
{
if(!getTexture(texture) && texture != 0)
{
Texture *textureObject;
if(type == TEXTURE_2D)
{
textureObject = new Texture2D(texture);
}
else if(type == TEXTURE_CUBE)
{
textureObject = new TextureCubeMap(texture);
}
else if(type == TEXTURE_EXTERNAL)
{
textureObject = new TextureExternal(texture);
}
else
{
UNREACHABLE();
return;
}
mTextureMap[texture] = textureObject;
textureObject->addRef();
}
}
}
// SwiftShader Software Renderer
//
// Copyright(c) 2005-2012 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//
// ResourceManager.h : Defines the ResourceManager class, which tracks objects
// shared by multiple GL contexts.
#ifndef LIBGLESV2_RESOURCEMANAGER_H_
#define LIBGLESV2_RESOURCEMANAGER_H_
#include "HandleAllocator.h"
#define GL_APICALL
#include <GLES2/gl2.h>
#include <map>
namespace es2
{
class Shader;
class Program;
class Texture;
class Renderbuffer;
enum TextureType
{
TEXTURE_2D,
TEXTURE_CUBE,
TEXTURE_EXTERNAL,
TEXTURE_TYPE_COUNT,
TEXTURE_UNKNOWN
};
class ResourceManager
{
public:
ResourceManager();
~ResourceManager();
void addRef();
void release();
GLuint createBuffer();
GLuint createShader(GLenum type);
GLuint createProgram();
GLuint createTexture();
GLuint createRenderbuffer();
void deleteShader(GLuint shader);
void deleteProgram(GLuint program);
void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer);
Shader *getShader(GLuint handle);
Program *getProgram(GLuint handle);
Texture *getTexture(GLuint handle);
Renderbuffer *getRenderbuffer(GLuint handle);
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
void checkTextureAllocation(GLuint texture, TextureType type);
private:
std::size_t mRefCount;
typedef std::map<GLint, Shader*> ShaderMap;
ShaderMap mShaderMap;
typedef std::map<GLint, Program*> ProgramMap;
ProgramMap mProgramMap;
HandleAllocator mProgramShaderHandleAllocator;
typedef std::map<GLint, Texture*> TextureMap;
TextureMap mTextureMap;
HandleAllocator mTextureHandleAllocator;
typedef std::map<GLint, Renderbuffer*> RenderbufferMap;
RenderbufferMap mRenderbufferMap;
HandleAllocator mRenderbufferHandleAllocator;
};
}
#endif // LIBGLESV2_RESOURCEMANAGER_H_
......@@ -26,7 +26,7 @@ namespace es2
{
bool Shader::compilerInitialized = false;
Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
Shader::Shader(GLuint handle) : mHandle(handle)
{
mSource = NULL;
mInfoLog = NULL;
......@@ -216,10 +216,10 @@ void Shader::release()
{
mRefCount--;
if(mRefCount == 0 && mDeleteStatus)
{
mResourceManager->deleteShader(mHandle);
}
if(mRefCount == 0)
{
delete this;
}
}
unsigned int Shader::getRefCount() const
......@@ -361,7 +361,7 @@ bool Shader::compareVarying(const Varying &x, const Varying &y)
return false;
}
VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
VertexShader::VertexShader(GLuint handle) : Shader(handle)
{
vertexShader = 0;
}
......@@ -447,7 +447,7 @@ sw::VertexShader *VertexShader::getVertexShader() const
return vertexShader;
}
FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
FragmentShader::FragmentShader(GLuint handle) : Shader(handle)
{
pixelShader = 0;
}
......
......@@ -17,8 +17,6 @@
#ifndef LIBGLESV2_SHADER_H_
#define LIBGLESV2_SHADER_H_
#include "ResourceManager.h"
#include "compiler/TranslatorASM.h"
#define GL_APICALL
......@@ -67,7 +65,7 @@ class Shader
friend class sh::OutputASM;
public:
Shader(ResourceManager *manager, GLuint handle);
Shader(GLuint handle);
virtual ~Shader();
......@@ -115,8 +113,6 @@ private:
const GLuint mHandle;
unsigned int mRefCount; // Number of program objects this shader is attached to
bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use
ResourceManager *mResourceManager;
};
class VertexShader : public Shader
......@@ -124,7 +120,7 @@ class VertexShader : public Shader
friend class Program;
public:
VertexShader(ResourceManager *manager, GLuint handle);
VertexShader(GLuint handle);
~VertexShader();
......@@ -142,7 +138,7 @@ private:
class FragmentShader : public Shader
{
public:
FragmentShader(ResourceManager *manager, GLuint handle);
FragmentShader(GLuint handle);
~FragmentShader();
......
......@@ -404,50 +404,6 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum form
Texture::setImage(format, type, unpackAlignment, pixels, image[level]);
}
void Texture2D::bindTexImage(egl::Surface *surface)
{
GLenum format;
switch(surface->getInternalFormat())
{
case sw::FORMAT_A8R8G8B8:
format = GL_RGBA;
break;
case sw::FORMAT_X8R8G8B8:
format = GL_RGB;
break;
default:
UNIMPLEMENTED();
return;
}
for(int level = 0; level < MIPMAP_LEVELS; level++)
{
if(image[level])
{
image[level]->unbind();
image[level] = 0;
}
}
image[0] = surface->getRenderTarget();
mSurface = surface;
mSurface->setBoundTexture(this);
}
void Texture2D::releaseTexImage()
{
for(int level = 0; level < MIPMAP_LEVELS; level++)
{
if(image[level])
{
image[level]->unbind();
image[level] = 0;
}
}
}
void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
if(image[level])
......
......@@ -139,8 +139,6 @@ public:
virtual bool isSamplerComplete() const;
virtual bool isCompressed(GLenum target, GLint level) const;
virtual bool isDepth(GLenum target, GLint level) const;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
virtual void generateMipmaps();
......
......@@ -33,7 +33,7 @@ VertexDataManager::~VertexDataManager()
GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated)
{
const VertexAttributeArray &attribs = mContext->getVertexAttributes();
Program *program = mContext->getCurrentProgram();
Program *program = mContext->mState.program;
// Perform the vertex data translations
for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
......
......@@ -322,7 +322,8 @@ class Program : public Object
public:
Program(Device *device) : Object(device)
{
program = new es2::Program(nullptr, 0);
program = new es2::Program(0);
program->addRef();
}
virtual ~Program()
......@@ -829,6 +830,7 @@ public:
}
image->unlock();
image->release();
}
Buffer *buffer;
......@@ -1391,8 +1393,10 @@ void RADAPIENTRY radProgramSource(RADprogram program, RADprogramFormat format, R
GLint vertexLength = strlen(vertexSource);
GLint fragmentLength = strlen(fragmentSource);
es2::VertexShader *vertexShader = new es2::VertexShader(nullptr, 0);
es2::FragmentShader *fragmentShader = new es2::FragmentShader(nullptr, 0);
es2::VertexShader *vertexShader = new es2::VertexShader(0);
vertexShader->addRef();
es2::FragmentShader *fragmentShader = new es2::FragmentShader(0);
fragmentShader->addRef();
vertexShader->setSource(1, &vertexSource, &vertexLength);
fragmentShader->setSource(1, &fragmentSource, &fragmentLength);
......@@ -1572,7 +1576,9 @@ RADrenderTargetHandle RADAPIENTRY radGetTextureRenderTargetHandle(RADtexture tex
default:
UNREACHABLE();
}
return reinterpret_cast<RADrenderTargetHandle>(radTexture->texture->getRenderTarget(glTarget, level));
egl::Image *image = radTexture->texture->getRenderTarget(glTarget, level);
image->release(); // FIXME: Handles are weak pointers
return reinterpret_cast<RADrenderTargetHandle>(image);
}
RADsampler RADAPIENTRY radCreateSampler(RADdevice device)
......
......@@ -175,7 +175,6 @@ copy "$(OutDir)libRAD.dll" "$(ProjectDir)..\..\..\lib\$(Configuration)\"</Comman
<ClCompile Include="Query.cpp" />
<ClCompile Include="RefCountObject.cpp" />
<ClCompile Include="Renderbuffer.cpp" />
<ClCompile Include="ResourceManager.cpp" />
<ClCompile Include="Shader.cpp" />
<ClCompile Include="Texture.cpp" />
<ClCompile Include="utilities.cpp" />
......@@ -201,7 +200,6 @@ copy "$(OutDir)libRAD.dll" "$(ProjectDir)..\..\..\lib\$(Configuration)\"</Comman
<ClInclude Include="RefCountObject.h" />
<ClInclude Include="Renderbuffer.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="ResourceManager.h" />
<ClInclude Include="Shader.h" />
<ClInclude Include="Texture.h" />
<ClInclude Include="utilities.h" />
......
......@@ -47,9 +47,6 @@
<ClCompile Include="Renderbuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ResourceManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Shader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
......@@ -109,9 +106,6 @@
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ResourceManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Shader.h">
<Filter>Header Files</Filter>
</ClInclude>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment