blob: 7cb8c8e72b32c5c7b5e486125533cb678622bd35 [file] [log] [blame]
/*
* gl_buffer.cpp - GL buffer
*
* Copyright (c) 2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Wind Yuan <[email protected]>
*/
#include "gl_buffer.h"
namespace XCam {
GLBufferDesc::GLBufferDesc ()
: format (V4L2_PIX_FMT_NV12)
, width (0)
, height (0)
, aligned_width (0)
, aligned_height (0)
, size (0)
{
xcam_mem_clear (strides);
xcam_mem_clear (slice_size);
xcam_mem_clear (offsets);
}
GLBuffer::MapRange::MapRange ()
: offset (0)
, len (0)
, flags (0)
, ptr (0)
{
}
void
GLBuffer::MapRange::clear ()
{
offset = 0;
len = 0;
flags = 0;
ptr = NULL;
}
bool
GLBuffer::MapRange::is_mapped () const
{
return ptr;
}
GLBuffer::GLBuffer (GLuint id, GLenum target, GLenum usage, uint32_t size)
: _target (target)
, _usage (usage)
, _buf_id (id)
, _size (size)
{
}
XCamReturn
GLBuffer::bind ()
{
glBindBuffer (_target, _buf_id);
GLenum error = gl_error ();
XCAM_FAIL_RETURN (
ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES,
"GL bind buffer:%d failed, error flag: %s", _buf_id, gl_error_string (error));
return XCAM_RETURN_NO_ERROR;
}
GLBuffer::~GLBuffer ()
{
if (_buf_id) {
glDeleteBuffers (1, &_buf_id);
GLenum error = gl_error ();
if (error != GL_NO_ERROR) {
XCAM_LOG_WARNING (
"GL Buffer delete buffer failed, error flag: %s", gl_error_string (error));
}
}
}
SmartPtr<GLBuffer>
GLBuffer::create_buffer (
GLenum target,
const GLvoid *data, uint32_t size,
GLenum usage)
{
XCAM_ASSERT (size > 0);
GLuint buf_id = 0;
glGenBuffers (1, &buf_id);
GLenum error = gl_error ();
XCAM_FAIL_RETURN (
ERROR, buf_id && (error == GL_NO_ERROR), NULL,
"GL buffer creation failed, error flag: %s", gl_error_string (error));
glBindBuffer (target, buf_id);
XCAM_FAIL_RETURN (
ERROR, (error = gl_error ()) == GL_NO_ERROR, NULL,
"GL buffer creation failed when bind buffer:%d, error flag: %s",
buf_id, gl_error_string (error));
glBufferData (target, size, data, usage);
XCAM_FAIL_RETURN (
ERROR, (error = gl_error ()) == GL_NO_ERROR, NULL,
"GL buffer creation failed in glBufferData, id:%d, error flag: %s",
buf_id, gl_error_string (error));
SmartPtr<GLBuffer> buf_obj =
new GLBuffer (buf_id, target, usage, size);
return buf_obj;
}
void *
GLBuffer::map_range (uint32_t offset, uint32_t length, GLbitfield flags)
{
if (length == 0)
length = _size;
if (_mapped_range.is_mapped () &&
_mapped_range.flags == flags &&
_mapped_range.offset == offset &&
_mapped_range.len == length) {
return _mapped_range.ptr;
}
_mapped_range.clear ();
XCamReturn ret = bind ();
XCAM_FAIL_RETURN (
ERROR, xcam_ret_is_ok (ret), NULL,
"GL bind buffer failed, buf_id:%d", _buf_id);
void *ptr = glMapBufferRange (_target, offset, length, flags);
GLenum error = gl_error ();
XCAM_FAIL_RETURN (
ERROR, ptr && (error == GL_NO_ERROR), NULL,
"GL buffer map range failed, buf_id:%d, offset:%d, len:%d, flags:%d, error flag: %s",
_buf_id, offset, length, flags, gl_error_string (error));
_mapped_range.offset = offset;
_mapped_range.len = length;
_mapped_range.flags = flags;
_mapped_range.ptr = ptr;
return ptr;
}
XCamReturn
GLBuffer::flush_map ()
{
if (!_mapped_range.is_mapped ())
return XCAM_RETURN_ERROR_ORDER;
XCAM_FAIL_RETURN (
ERROR, _mapped_range.flags & GL_MAP_FLUSH_EXPLICIT_BIT,
XCAM_RETURN_ERROR_GLES,
"GL buffer flush_map buf:%d failed, invalid flags(:%d)",
_buf_id, _mapped_range.flags);
XCamReturn ret = bind ();
XCAM_FAIL_RETURN (
ERROR, xcam_ret_is_ok (ret), ret,
"GL bind buffer failed, buf_id:%d", _buf_id);
glFlushMappedBufferRange (_target, _mapped_range.offset, _mapped_range.len);
GLenum error = gl_error ();
XCAM_FAIL_RETURN (
ERROR, error == GL_NO_ERROR,
XCAM_RETURN_ERROR_GLES,
"GL buffer flush_map buf:%d failed, error flag: %s",
_buf_id, gl_error_string (error));
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
GLBuffer::unmap ()
{
if (!_mapped_range.is_mapped ())
return XCAM_RETURN_ERROR_ORDER;
XCamReturn ret = bind ();
XCAM_FAIL_RETURN (
ERROR, xcam_ret_is_ok (ret), ret,
"GL bind buffer failed, buf_id:%d", _buf_id);
XCAM_FAIL_RETURN (
ERROR, glUnmapBuffer (_target), XCAM_RETURN_ERROR_GLES,
"GL buffer unmap buf:%d failed, error flag: %s",
_buf_id, gl_error_string (gl_error ()));
_mapped_range.clear ();
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
GLBuffer::bind_buffer_base (uint32_t index)
{
XCamReturn ret = bind ();
XCAM_FAIL_RETURN (
ERROR, xcam_ret_is_ok (ret), ret,
"GL bind buffer failed, buf_id:%d", _buf_id);
glBindBufferBase (_target, index, _buf_id);
GLenum error = gl_error ();
XCAM_FAIL_RETURN (
ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES,
"GL bind buffer base failed. buf_id:%d failed, idx:%d, error flag: %s",
_buf_id, index, gl_error_string (error));
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
GLBuffer::bind_buffer_range (uint32_t index, uint32_t offset, uint32_t size)
{
XCamReturn ret = bind ();
XCAM_FAIL_RETURN (
ERROR, xcam_ret_is_ok (ret), ret,
"GL bind buffer failed, buf_id:%d", _buf_id);
glBindBufferRange (_target, index, _buf_id, offset, size);
GLenum error = gl_error ();
XCAM_FAIL_RETURN (
ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES,
"GL bind buffer range failed. buf_id:%d failed, idx:%d, error flag: %s",
_buf_id, index, gl_error_string (error));
return XCAM_RETURN_NO_ERROR;
}
}