blob: 94510c68d39dbdcfae21f238f54f84474c7826f1 [file] [log] [blame]
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FramebufferNULL.cpp:
// Implements the class methods for FramebufferNULL.
//
#include "libANGLE/renderer/null/FramebufferNULL.h"
#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/null/BufferNULL.h"
#include "libANGLE/renderer/null/ContextNULL.h"
namespace rx
{
FramebufferNULL::FramebufferNULL(const gl::FramebufferState &state) : FramebufferImpl(state) {}
FramebufferNULL::~FramebufferNULL() {}
angle::Result FramebufferNULL::discard(const gl::Context *context,
size_t count,
const GLenum *attachments)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::invalidate(const gl::Context *context,
size_t count,
const GLenum *attachments)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::invalidateSub(const gl::Context *context,
size_t count,
const GLenum *attachments,
const gl::Rectangle &area)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::clear(const gl::Context *context, GLbitfield mask)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::clearBufferiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLint *values)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
GLint stencil)
{
return angle::Result::Continue;
}
GLenum FramebufferNULL::getImplementationColorReadFormat(const gl::Context *context) const
{
const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
if (readAttachment == nullptr)
{
return GL_NONE;
}
const gl::Format &format = readAttachment->getFormat();
ASSERT(format.info != nullptr);
return format.info->getReadPixelsFormat(context->getExtensions());
}
GLenum FramebufferNULL::getImplementationColorReadType(const gl::Context *context) const
{
const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
if (readAttachment == nullptr)
{
return GL_NONE;
}
const gl::Format &format = readAttachment->getFormat();
ASSERT(format.info != nullptr);
return format.info->getReadPixelsType(context->getClientVersion());
}
angle::Result FramebufferNULL::readPixels(const gl::Context *context,
const gl::Rectangle &origArea,
GLenum format,
GLenum type,
void *ptrOrOffset)
{
const gl::PixelPackState &packState = context->getState().getPackState();
gl::Buffer *packBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelPack);
// Get the pointer to write to from the argument or the pack buffer
GLubyte *pixels = nullptr;
if (packBuffer != nullptr)
{
BufferNULL *packBufferGL = GetImplAs<BufferNULL>(packBuffer);
pixels = reinterpret_cast<GLubyte *>(packBufferGL->getDataPtr());
pixels += reinterpret_cast<intptr_t>(ptrOrOffset);
}
else
{
pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
}
// Clip read area to framebuffer.
const gl::Extents fbSize = getState().getReadAttachment()->getSize();
const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
gl::Rectangle area;
if (!ClipRectangle(origArea, fbRect, &area))
{
// nothing to read
return angle::Result::Continue;
}
// Compute size of unclipped rows and initial skip
const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
ContextNULL *contextNull = GetImplAs<ContextNULL>(context);
GLuint rowBytes = 0;
ANGLE_CHECK_GL_MATH(contextNull,
glFormat.computeRowPitch(type, origArea.width, packState.alignment,
packState.rowLength, &rowBytes));
GLuint skipBytes = 0;
ANGLE_CHECK_GL_MATH(contextNull,
glFormat.computeSkipBytes(type, rowBytes, 0, packState, false, &skipBytes));
pixels += skipBytes;
// Skip OOB region up to first in bounds pixel
int leftClip = area.x - origArea.x;
int topClip = area.y - origArea.y;
pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
// Write the in-bounds readpixels data with non-zero values
for (GLint y = area.y; y < area.y + area.height; ++y)
{
memset(pixels, 42, glFormat.pixelBytes * area.width);
pixels += rowBytes;
}
return angle::Result::Continue;
}
angle::Result FramebufferNULL::blit(const gl::Context *context,
const gl::Rectangle &sourceArea,
const gl::Rectangle &destArea,
GLbitfield mask,
GLenum filter)
{
return angle::Result::Continue;
}
bool FramebufferNULL::checkStatus(const gl::Context *context) const
{
return true;
}
angle::Result FramebufferNULL::syncState(const gl::Context *context,
const gl::Framebuffer::DirtyBits &dirtyBits)
{
return angle::Result::Continue;
}
angle::Result FramebufferNULL::getSamplePosition(const gl::Context *context,
size_t index,
GLfloat *xy) const
{
return angle::Result::Continue;
}
} // namespace rx