grab_XXX functions are temporarily removed

This commit is contained in:
2019-07-23 05:35:08 +07:00
parent 010da6e620
commit 22f88a7bdd
5 changed files with 8 additions and 325 deletions

View File

@@ -961,23 +961,6 @@ namespace e2d
buffer_view pixels,
const b2u& region);
// very slow
render& grab_texture(
const texture_ptr& tex,
const b2u& region,
image& result);
// very slow
render& grab_render_target(
const render_target_ptr& rt,
const b2u& region,
image& result);
// very slow
render& grab_screen(
const b2u& region,
image& result);
const device_caps& device_capabilities() const noexcept;
bool is_pixel_supported(const pixel_declaration& decl) const noexcept;
bool is_index_supported(const index_declaration& decl) const noexcept;

View File

@@ -287,35 +287,6 @@ namespace e2d
return *this;
}
render& render::grab_texture(
const texture_ptr& tex,
const b2u& region,
image& result)
{
E2D_UNUSED(tex, region);
result.clear();
return *this;
}
render& render::grab_render_target(
const render_target_ptr& rt,
const b2u& region,
image& result)
{
E2D_UNUSED(rt, region);
result.clear();
return *this;
}
render& render::grab_screen(
const b2u& region,
image& result)
{
E2D_UNUSED(tex);
result.clear();
return *this;
}
const render::device_caps& render::device_capabilities() const noexcept {
static device_caps caps;
return caps;

View File

@@ -301,147 +301,6 @@ namespace
static render::property_block props;
return props;
}
void grab_framebuffer_content(
debug& debug,
const opengl::gl_framebuffer_id& fb,
const b2u& region,
image& result)
{
with_gl_bind_framebuffer(debug, fb,
[&debug, &region, &result]() {
GLint format;
GLint type;
GL_CHECK_CODE(debug, glGetIntegerv(
GL_IMPLEMENTATION_COLOR_READ_FORMAT,
&format));
GL_CHECK_CODE(debug, glGetIntegerv(
GL_IMPLEMENTATION_COLOR_READ_TYPE,
&type));
image_data_format img_format;
if ( (format == GL_ALPHA || format == GL_LUMINANCE) && type == GL_UNSIGNED_BYTE ) {
img_format = image_data_format::g8;
} else if ( format == GL_RGB && type == GL_UNSIGNED_BYTE ) {
img_format = image_data_format::rgb8;
} else if ( format == GL_RGBA && type == GL_UNSIGNED_BYTE ) {
img_format = image_data_format::rgba8;
} else {
E2D_ASSERT_MSG(false, "unsupported pixel format");
// OpenGL ES 2 already supports RGBA8 format for glReadPixels
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
img_format = image_data_format::rgba8;
}
pixel_declaration decl = convert_image_data_format_to_pixel_declaration(img_format);
buffer pixels;
pixels.resize(((decl.bits_per_pixel() * region.size.x) / 8u) * region.size.y);
GL_CHECK_CODE(debug, glReadPixels(
math::numeric_cast<GLint>(region.position.x),
math::numeric_cast<GLint>(region.position.y),
math::numeric_cast<GLsizei>(region.size.x),
math::numeric_cast<GLsizei>(region.size.y),
format,
type,
pixels.data()));
result = image(region.size, img_format, std::move(pixels));
});
}
void grab_compressed_texture(
render& render,
const texture_ptr& tex,
const b2u& region,
image& result)
{
const char vs_source[] = R"glsl(
#version 120
attribute vec2 a_position;
varying vec2 v_uv;
void main(){
v_uv = a_position * 0.5 + 0.5;
gl_Position = vec4(a_position.xy, 0.0, 1.0);
}
)glsl";
const char fs_source[] = R"glsl(
#version 120
uniform sampler2D u_texture;
varying vec2 v_uv;
void main(){
gl_FragColor = texture2D(u_texture, v_uv);
}
)glsl";
const v2f vertices[] = {
v2f(-1.0f, 1.0f), v2f(-1.0f, -1.0f), v2f(1.0f, 1.0f), v2f(1.0f, -1.0f)
};
shader_ptr shader = render.create_shader(vs_source, fs_source);
if ( !shader ) {
throw bad_render_operation();
}
vertex_buffer_ptr vbuffer = render.create_vertex_buffer(
buffer_view(vertices),
vertex_declaration().add_attribute<v2f>("a_position"),
vertex_buffer::usage::static_draw);
if ( !vbuffer ) {
throw bad_render_operation();
}
render::geometry geometry;
geometry.add_vertices(vbuffer);
geometry.topo(render::topology::triangles_strip);
render::material material;
material.add_pass(render::pass_state()
.shader(shader)
.properties(render::property_block()
.sampler("u_texture", render::sampler_state()
.texture(tex)
.min_filter(render::sampler_min_filter::nearest)
.mag_filter(render::sampler_mag_filter::nearest))));
// convert compressed format to non-compressed
const auto convert_to_noncompressed = [](pixel_declaration decl) {
#define DEFINE_CASE(x, y) case pixel_declaration::pixel_type::x: return pixel_declaration::pixel_type::y;
switch ( decl.type() ) {
DEFINE_CASE(rgb_dxt1, rgba8)
DEFINE_CASE(rgba_dxt1, rgba8)
DEFINE_CASE(rgba_dxt3, rgba8)
DEFINE_CASE(rgba_dxt5, rgba8)
DEFINE_CASE(rgb_pvrtc2, rgba8)
DEFINE_CASE(rgb_pvrtc4, rgba8)
DEFINE_CASE(rgba_pvrtc2, rgba8)
DEFINE_CASE(rgba_pvrtc4, rgba8)
DEFINE_CASE(rgba_pvrtc2_v2, rgba8)
DEFINE_CASE(rgba_pvrtc4_v2, rgba8)
default:
E2D_ASSERT_MSG(false, "unexpected pixel format");
return pixel_declaration::pixel_type::rgba8;
}
#undef DEFINE_CASE
};
render_target_ptr rt = render.create_render_target(
tex->size(),
convert_to_noncompressed(tex->decl()),
pixel_declaration::pixel_type::depth16,
render_target::external_texture::color);
render.execute(render::viewport_command(b2u(tex->size())));
render.execute(render::target_command(rt));
render.execute(render::draw_command(material, geometry));
render.grab_render_target(rt, region, result);
}
}
namespace e2d
@@ -1228,71 +1087,6 @@ namespace e2d
return *this;
}
render& render::grab_texture(
const texture_ptr& tex,
const b2u& region,
image& result)
{
E2D_ASSERT(tex);
E2D_ASSERT(tex->decl().is_color());
E2D_ASSERT(region.size.x > 0 && region.size.y > 0);
E2D_ASSERT(region.position.x + region.size.x <= tex->size().x);
E2D_ASSERT(region.position.y + region.size.y <= tex->size().y);
if ( tex->decl().is_compressed() ) {
grab_compressed_texture(*this, tex, region, result);
return *this;
}
gl_framebuffer_id id = gl_framebuffer_id::create(state_->dbg(), GL_FRAMEBUFFER);
if ( id.empty() ) {
throw bad_render_operation();
}
gl_attach_texture(state_->dbg(), id, tex->state().id(), GL_COLOR_ATTACHMENT0);
GLenum fb_status = GL_FRAMEBUFFER_COMPLETE;
if ( !gl_check_framebuffer(state_->dbg(), id, &fb_status) ) {
throw bad_render_operation();
}
grab_framebuffer_content(
state_->dbg(),
id,
region,
result);
return *this;
}
render& render::grab_render_target(
const render_target_ptr& rt,
const b2u& region,
image& result)
{
E2D_ASSERT(rt);
E2D_ASSERT(region.size.x > 0 && region.size.y > 0);
E2D_ASSERT(region.position.x + region.size.x <= rt->size().x);
E2D_ASSERT(region.position.y + region.size.y <= rt->size().y);
grab_framebuffer_content(
state_->dbg(),
rt->state().id(),
region,
result);
return *this;
}
render& render::grab_screen(
const b2u& region,
image& result)
{
E2D_ASSERT(region.size.x > 0 && region.size.y > 0);
E2D_ASSERT(region.position.x + region.size.x <= state_->wnd().real_size().x);
E2D_ASSERT(region.position.y + region.size.y <= state_->wnd().real_size().y);
grab_framebuffer_content(
state_->dbg(),
state_->default_fb(),
region,
result);
return *this;
}
const render::device_caps& render::device_capabilities() const noexcept {
E2D_ASSERT(is_in_main_thread());
return state_->device_capabilities();

View File

@@ -17,7 +17,6 @@
#if defined(E2D_BUILD_MODE) && E2D_BUILD_MODE == E2D_BUILD_MODE_DEBUG
# define GL_FLUSH_ERRORS(dbg)\
for ( GLenum err = glGetError(); err != GL_NO_ERROR; err = glGetError() ) {\
E2D_ASSERT_MSG(false, "RENDER: GL_FLUSH_ERRORS()");\
(dbg).log(err == GL_OUT_OF_MEMORY\
? debug::level::fatal\
: debug::level::error,\
@@ -26,13 +25,13 @@
"--> Line: %1\n"\
"--> Code: %2",\
__FILE__, __LINE__, e2d::opengl::gl_error_code_to_cstr(err));\
E2D_ASSERT_MSG(false, "RENDER: GL_FLUSH_ERRORS()");\
if ( err == GL_OUT_OF_MEMORY ) std::terminate();\
}
# define GL_CHECK_CODE(dbg, code)\
GL_FLUSH_ERRORS(dbg);\
code;\
for ( GLenum err = glGetError(); err != GL_NO_ERROR; err = glGetError() ) {\
E2D_ASSERT_MSG(false, #code);\
(dbg).log(err == GL_OUT_OF_MEMORY\
? debug::level::fatal\
: debug::level::error,\
@@ -41,6 +40,7 @@
"--> Line: %2\n"\
"--> Code: %3",\
#code, __FILE__, __LINE__, e2d::opengl::gl_error_code_to_cstr(err));\
E2D_ASSERT_MSG(false, #code);\
if ( err == GL_OUT_OF_MEMORY ) std::terminate();\
}
#else

View File

@@ -198,12 +198,7 @@ TEST_CASE("render"){
for ( auto& c : src ) {
c = rand() % 255;
}
r.update_texture(tex, src, b2u(0, 0, 128, 128));
image dst;
r.grab_texture(tex, b2u(0, 0, 128, 128), dst);
REQUIRE(dst.format() == image_data_format::rgba8);
REQUIRE(src == dst.data());
REQUIRE_NOTHROW(r.update_texture(tex, src, b2u(0, 0, 128, 128)));
}
{
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::g8);
@@ -214,22 +209,7 @@ TEST_CASE("render"){
for ( auto& c : src ) {
c = rand() % 255;
}
r.update_texture(tex, src, b2u(0, 0, 128, 128));
image dst;
r.grab_texture(tex, b2u(0, 0, 128, 128), dst);
if ( dst.format() == image_data_format::g8 ) {
REQUIRE(src == dst.data());
} else {
// OpenGL ES 2 may not support Alpha8 format
REQUIRE(dst.format() == image_data_format::rgba8);
REQUIRE(dst.data().size() == src.size()*4);
bool equal = true;
for ( size_t i = 0; i < src.size(); ++i ) {
equal &= (src.data()[i] == dst.data().data()[i*4+3]);
}
REQUIRE(equal);
}
REQUIRE_NOTHROW(r.update_texture(tex, src, b2u(0, 0, 128, 128)));
}
{
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::rgb8);
@@ -240,24 +220,7 @@ TEST_CASE("render"){
for ( auto& c : src ) {
c = rand() % 255;
}
r.update_texture(tex, src, b2u(0, 0, 128, 128));
image dst;
r.grab_texture(tex, b2u(0, 0, 128, 128), dst);
if ( dst.format() == image_data_format::rgb8 ) {
REQUIRE(src == dst.data());
} else {
// OpenGL ES 2 may not support RGB8 format
REQUIRE(dst.format() == image_data_format::rgba8);
REQUIRE(dst.data().size() == src.size()*4/3);
bool equal = true;
for ( size_t i = 0, j = 0; i < src.size(); i += 3, j += 4 ) {
equal &= (src.data()[i+0] == dst.data().data()[j+0]);
equal &= (src.data()[i+1] == dst.data().data()[j+1]);
equal &= (src.data()[i+2] == dst.data().data()[j+2]);
}
REQUIRE(equal);
}
REQUIRE_NOTHROW(r.update_texture(tex, src, b2u(0, 0, 128, 128)));
}
{
texture_ptr tex = r.create_texture(v2u(57,31), pixel_declaration::pixel_type::rgba8);
@@ -268,12 +231,7 @@ TEST_CASE("render"){
for ( auto& c : src ) {
c = rand() % 255;
}
r.update_texture(tex, src, b2u(0, 0, 57, 31));
image dst;
r.grab_texture(tex, b2u(0, 0, 57, 31), dst);
REQUIRE(dst.format() == image_data_format::rgba8);
REQUIRE(src == dst.data());
REQUIRE_NOTHROW(r.update_texture(tex, src, b2u(0, 0, 57, 31)));
}
{
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::rgba8);
@@ -284,25 +242,7 @@ TEST_CASE("render"){
for ( auto& c : src ) {
c = rand() % 255;
}
r.update_texture(tex, src, b2u(22, 17, 31, 44));
image dst;
r.grab_texture(tex, b2u(0, 0, 128, 128), dst);
REQUIRE(dst.format() == image_data_format::rgba8);
const size_t data_size = ((tex->size().x * tex->decl().bits_per_pixel()) / 8u) * tex->size().y;
REQUIRE(data_size == dst.data().size());
bool equal = true;
const size_t bpp = tex->decl().bits_per_pixel() / 8;
for ( u32 y = 0; y < 44; ++y ) {
const u8* dst_row = dst.data().data() + ((y + 17) * 128 + 22) * bpp;
const u8* src_row = src.data() + (y * 31 * bpp);
for ( u32 x = 0; x < 31 * bpp; ++x ) {
equal &= (src_row[x] == dst_row[x]);
}
}
REQUIRE(equal);
REQUIRE_NOTHROW(r.update_texture(tex, src, b2u(22, 17, 31, 44)));
}
{
texture_ptr tex = r.create_texture(v2u(128,128), pixel_declaration::pixel_type::rgba8);
@@ -332,12 +272,7 @@ TEST_CASE("render"){
texture_ptr tex = r.create_texture(src.size(), pixel_declaration::pixel_type::rgba_dxt5);
REQUIRE(tex != nullptr);
r.update_texture(tex, src, v2u(0,0));
image dst;
r.grab_texture(tex, b2u(src.size()), dst);
REQUIRE(dst.format() == image_data_format::rgba8);
REQUIRE(src.size() == dst.size());
REQUIRE_NOTHROW(r.update_texture(tex, src, v2u(0,0)));
}
}
}