Implement copies from pack buffers to native buffers.

Full support for using pack buffers as vertex buffers or other
binding points requires us to copy through the staging buffer.

BUG=angle:511

Change-Id: Ife0f5390a1a83dfbe0fa0b19db72f3a8b82b6b83
Reviewed-on: https://chromium-review.googlesource.com/198435
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Jamie Madill 2014-05-08 10:19:36 -04:00
Родитель 14764a0928
Коммит 5fedd0174b
2 изменённых файлов: 77 добавлений и 0 удалений

Просмотреть файл

@ -82,6 +82,7 @@ class BufferStorage11::TypedBufferStorage11
DataRevision getDataRevision() const { return mRevision; }
BufferUsage getUsage() const { return mUsage; }
size_t getSize() const { return mBufferSize; }
bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); }
void setDataRevision(DataRevision rev) { mRevision = rev; }
@ -274,6 +275,17 @@ void BufferStorage11::copyData(BufferStorage* sourceStorage, size_t size, size_t
TypedBufferStorage11 *source = sourceStorage11->getLatestStorage();
if (source && dest)
{
// If copying to/from a pixel pack buffer, we must have a staging or
// pack buffer partner, because other native buffers can't be mapped
if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable())
{
source = sourceStorage11->getStagingBuffer();
}
else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable())
{
dest = getStagingBuffer();
}
dest->copyFromStorage(source, sourceOffset, size, destOffset);
dest->setDataRevision(dest->getDataRevision() + 1);
}
@ -433,6 +445,18 @@ BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage u
TypedBufferStorage11 *latestBuffer = getLatestStorage();
if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision())
{
// if copying from a pack buffer to a non-staging native buffer, we must first
// copy through the staging buffer, because other native buffers can't be mapped
if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable())
{
NativeBuffer11 *stagingBuffer = getStagingBuffer();
stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0);
directBuffer->setDataRevision(latestBuffer->getDataRevision());
latestBuffer = stagingBuffer;
}
// if copyFromStorage returns true, the D3D buffer has been recreated
// and we should update our serial
if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0))

Просмотреть файл

@ -240,3 +240,56 @@ TEST_F(ReadPixelsTest, pbo_and_sub_data_offset)
glUnmapBuffer(GL_ARRAY_BUFFER);
EXPECT_GL_NO_ERROR();
}
TEST_F(ReadPixelsTest, draw_with_pbo)
{
unsigned char data[4] = { 1, 2, 3, 4 };
glBindTexture(GL_TEXTURE_2D, mTexture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
EXPECT_GL_NO_ERROR();
// glReadBuffer(GL_COLOR_ATTACHMENT0); // FIXME: currently UNIMPLEMENTED
glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO);
EXPECT_GL_NO_ERROR();
glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
EXPECT_GL_NO_ERROR();
float positionData[] = { 0.5f, 0.5f };
glUseProgram(mProgram);
glViewport(0, 0, 1, 1);
glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, 1 * 2 * 4, positionData);
EXPECT_GL_NO_ERROR();
GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
EXPECT_NE(-1, positionLocation);
GLint testLocation = glGetAttribLocation(mProgram, "aTest");
EXPECT_NE(-1, testLocation);
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(positionLocation);
EXPECT_GL_NO_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, mPBO);
glVertexAttribPointer(testLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
glEnableVertexAttribArray(testLocation);
EXPECT_GL_NO_ERROR();
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR();
memset(data, 0, 4);
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(1, data[0]);
EXPECT_EQ(2, data[1]);
EXPECT_EQ(3, data[2]);
EXPECT_EQ(4, data[3]);
}