Commit d1ed57e6 by Nicolas Capens Committed by Nicolas Capens

Implement GL_NV_read_depth_stencil.

Bug swiftshader:104 Change-Id: I9fcea0c76875de735c3bad0a5c587875d0ca4e26 Reviewed-on: https://swiftshader-review.googlesource.com/18089Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarLingfeng Yang <lfy@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 0c6ac93c
...@@ -160,6 +160,14 @@ namespace gl ...@@ -160,6 +160,14 @@ namespace gl
default: UNREACHABLE(type); default: UNREACHABLE(type);
} }
break; break;
case GL_STENCIL_INDEX_OES:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_S8;
default: UNREACHABLE(type);
}
break;
case GL_DEPTH_STENCIL_OES: // Cannot be read as one format. Handled separately.
default: default:
UNREACHABLE(format); UNREACHABLE(format);
break; break;
......
...@@ -3323,8 +3323,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum ...@@ -3323,8 +3323,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
switch(format) switch(format)
{ {
case GL_DEPTH_COMPONENT: // GL_NV_read_depth case GL_DEPTH_COMPONENT: // GL_NV_read_depth
case GL_DEPTH_STENCIL_OES: // GL_NV_read_depth_stencil
renderTarget = framebuffer->getDepthBuffer(); renderTarget = framebuffer->getDepthBuffer();
break; break;
case GL_STENCIL_INDEX_OES: // GL_NV_read_stencil
renderTarget = framebuffer->getStencilBuffer();
break;
default: default:
renderTarget = framebuffer->getReadRenderTarget(); renderTarget = framebuffer->getReadRenderTarget();
break; break;
...@@ -3339,11 +3343,64 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum ...@@ -3339,11 +3343,64 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
sw::SliceRect dstRect(0, 0, width, height, 0); sw::SliceRect dstRect(0, 0, width, height, 0);
srcRect.clip(0.0f, 0.0f, (float)renderTarget->getWidth(), (float)renderTarget->getHeight()); srcRect.clip(0.0f, 0.0f, (float)renderTarget->getWidth(), (float)renderTarget->getHeight());
if(format != GL_DEPTH_STENCIL_OES) // The blitter only handles reading either depth or stencil.
{
sw::Surface *externalSurface = sw::Surface::create(width, height, 1, gl::ConvertReadFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight); sw::Surface *externalSurface = sw::Surface::create(width, height, 1, gl::ConvertReadFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight);
device->blit(renderTarget, srcRect, externalSurface, dstRect, false, false, false); device->blit(renderTarget, srcRect, externalSurface, dstRect, false, false, false);
externalSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); externalSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
externalSurface->unlockExternal(); externalSurface->unlockExternal();
delete externalSurface; delete externalSurface;
}
else // format == GL_DEPTH_STENCIL_OES
{
ASSERT(renderTarget->getInternalFormat() == sw::FORMAT_D32F_LOCKABLE);
float *depth = (float*)renderTarget->lockInternal((int)srcRect.x0, (int)srcRect.y0, 0, sw::LOCK_READONLY, sw::PUBLIC);
uint8_t *stencil = (uint8_t*)renderTarget->lockStencil((int)srcRect.x0, (int)srcRect.y0, 0, sw::PUBLIC);
switch(type)
{
case GL_UNSIGNED_INT_24_8_OES:
{
uint32_t *output = (uint32_t*)pixels;
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{
output[x] = ((uint32_t)roundf(depth[x] * 0xFFFFFF00) & 0xFFFFFF00) | stencil[x];
}
depth += renderTarget->getInternalPitchP();
stencil += renderTarget->getStencilPitchB();
(uint8_t*&)output += outputPitch;
}
}
break;
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
{
struct D32FS8 { float depth32f; unsigned int stencil24_8; };
D32FS8 *output = (D32FS8*)pixels;
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{
output[x].depth32f = depth[x];
output[x].stencil24_8 = stencil[x];
}
depth += renderTarget->getInternalPitchP();
stencil += renderTarget->getStencilPitchB();
(uint8_t*&)output += outputPitch;
}
}
break;
default: UNREACHABLE(type);
}
renderTarget->unlockInternal();
renderTarget->unlockStencil();
}
renderTarget->release(); renderTarget->release();
} }
...@@ -4441,9 +4498,12 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const ...@@ -4441,9 +4498,12 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const
"GL_APPLE_texture_format_BGRA8888", "GL_APPLE_texture_format_BGRA8888",
"GL_CHROMIUM_color_buffer_float_rgba", // A subset of EXT_color_buffer_float on top of OpenGL ES 2.0 "GL_CHROMIUM_color_buffer_float_rgba", // A subset of EXT_color_buffer_float on top of OpenGL ES 2.0
"GL_CHROMIUM_texture_filtering_hint", "GL_CHROMIUM_texture_filtering_hint",
"GL_NV_depth_buffer_float2",
"GL_NV_fence", "GL_NV_fence",
"GL_NV_framebuffer_blit", "GL_NV_framebuffer_blit",
"GL_NV_read_depth", "GL_NV_read_depth",
"GL_NV_read_depth_stencil",
"GL_NV_read_stencil",
}; };
GLuint numExtensions = sizeof(extensions) / sizeof(extensions[0]); GLuint numExtensions = sizeof(extensions) / sizeof(extensions[0]);
......
...@@ -677,6 +677,70 @@ namespace es2 ...@@ -677,6 +677,70 @@ namespace es2
return true; return true;
} }
// GL_NV_read_depth_stencil
if(format == GL_DEPTH_STENCIL_OES)
{
Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
if(!depthbuffer)
{
return error(GL_INVALID_OPERATION, false);
}
GLint internalformat = depthbuffer->getFormat();
switch(type)
{
case GL_UNSIGNED_INT_24_8_OES:
switch(internalformat)
{
case GL_DEPTH24_STENCIL8:
break;
case GL_DEPTH32F_STENCIL8:
return error(GL_INVALID_OPERATION, false);
default:
UNREACHABLE(internalformat);
return error(GL_INVALID_OPERATION, false);
}
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
switch(internalformat)
{
case GL_DEPTH32F_STENCIL8:
break;
case GL_DEPTH24_STENCIL8:
return error(GL_INVALID_OPERATION, false);
default:
UNREACHABLE(internalformat);
return error(GL_INVALID_OPERATION, false);
}
default:
return error(GL_INVALID_ENUM, false);
}
return true;
}
// GL_NV_read_stencil
if(format == GL_STENCIL_INDEX_OES)
{
Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
if(!stencilbuffer)
{
return error(GL_INVALID_OPERATION, false);
}
switch(type)
{
case GL_UNSIGNED_BYTE:
break;
default:
return error(GL_INVALID_ENUM, false);
}
return true;
}
Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
if(!colorbuffer) if(!colorbuffer)
......
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