mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:07:47 +00:00
LibGL: Implement glBindTexture()
Textures are now initialized with a nullptr upon generation. They are only actually created once they are bound to a target. Currently only the GL_TEXTURE_2D target is supported. The software rasterizer now allows rendering with or without a bound TEXTURE_2D.
This commit is contained in:
parent
fde0045ebe
commit
755393e684
8 changed files with 85 additions and 4 deletions
|
@ -153,6 +153,7 @@ bool GLContextWidget::load(const String& filename)
|
||||||
glGenTextures(1, &tex);
|
glGenTextures(1, &tex);
|
||||||
if (texture_image) {
|
if (texture_image) {
|
||||||
// Upload texture data to the GL
|
// Upload texture data to the GL
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_image->width(), texture_image->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_image->scanline(0));
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_image->width(), texture_image->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_image->scanline(0));
|
||||||
} else {
|
} else {
|
||||||
dbgln("3DFileViewer: Couldn't load texture for {}", filename);
|
dbgln("3DFileViewer: Couldn't load texture for {}", filename);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
|
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
|
||||||
|
* Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -257,6 +258,7 @@ GLAPI void glReadBuffer(GLenum mode);
|
||||||
GLAPI void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
|
GLAPI void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
|
||||||
GLAPI void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data);
|
GLAPI void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data);
|
||||||
GLAPI void glTexCoord2f(GLfloat s, GLfloat t);
|
GLAPI void glTexCoord2f(GLfloat s, GLfloat t);
|
||||||
|
GLAPI void glBindTexture(GLenum target, GLuint texture);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = 0;
|
virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = 0;
|
||||||
virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) = 0;
|
virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) = 0;
|
||||||
virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) = 0;
|
virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) = 0;
|
||||||
|
virtual void gl_bind_texture(GLenum target, GLuint texture) = 0;
|
||||||
|
|
||||||
virtual void present() = 0;
|
virtual void present() = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
|
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
|
||||||
|
* Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -23,3 +24,8 @@ void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei widt
|
||||||
{
|
{
|
||||||
g_gl_context->gl_tex_image_2d(target, level, internalFormat, width, height, border, format, type, data);
|
g_gl_context->gl_tex_image_2d(target, level, internalFormat, width, height, border, format, type, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void glBindTexture(GLenum target, GLuint texture)
|
||||||
|
{
|
||||||
|
g_gl_context->gl_bind_texture(target, texture);
|
||||||
|
}
|
||||||
|
|
|
@ -313,7 +313,12 @@ void SoftwareGLContext::gl_end()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Change this when we have texture units/multi-texturing
|
// FIXME: Change this when we have texture units/multi-texturing
|
||||||
m_rasterizer.submit_triangle(triangle, *static_ptr_cast<Texture2D>(m_allocated_textures.find(1)->value));
|
if (m_bound_texture_2d == 0) {
|
||||||
|
m_rasterizer.submit_triangle(triangle);
|
||||||
|
} else {
|
||||||
|
auto it = m_allocated_textures.find(m_bound_texture_2d);
|
||||||
|
m_rasterizer.submit_triangle(triangle, *static_ptr_cast<Texture2D>(it->value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
triangle_list.clear();
|
triangle_list.clear();
|
||||||
|
@ -663,11 +668,11 @@ void SoftwareGLContext::gl_gen_textures(GLsizei n, GLuint* textures)
|
||||||
|
|
||||||
m_name_allocator.allocate(n, textures);
|
m_name_allocator.allocate(n, textures);
|
||||||
|
|
||||||
// Let's allocate a new texture for each texture name
|
// Initialize all texture names with a nullptr
|
||||||
for (auto i = 0; i < n; i++) {
|
for (auto i = 0; i < n; i++) {
|
||||||
GLuint name = textures[i];
|
GLuint name = textures[i];
|
||||||
|
|
||||||
m_allocated_textures.set(name, adopt_ref(*new Texture2D()));
|
m_allocated_textures.set(name, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,10 +683,13 @@ void SoftwareGLContext::gl_delete_textures(GLsizei n, const GLuint* textures)
|
||||||
|
|
||||||
m_name_allocator.free(n, textures);
|
m_name_allocator.free(n, textures);
|
||||||
|
|
||||||
// Let's allocate a new texture for each texture name
|
|
||||||
for (auto i = 0; i < n; i++) {
|
for (auto i = 0; i < n; i++) {
|
||||||
GLuint name = textures[i];
|
GLuint name = textures[i];
|
||||||
|
|
||||||
|
// unbind texture if it is currently bound
|
||||||
|
if (m_bound_texture_2d == name)
|
||||||
|
m_bound_texture_2d = 0;
|
||||||
|
|
||||||
m_allocated_textures.remove(name);
|
m_allocated_textures.remove(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -693,6 +701,9 @@ void SoftwareGLContext::gl_tex_image_2d(GLenum target, GLint level, GLint intern
|
||||||
// We only support GL_TEXTURE_2D for now
|
// We only support GL_TEXTURE_2D for now
|
||||||
RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
|
RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
|
||||||
|
|
||||||
|
// Check if there is actually a texture bound
|
||||||
|
RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && m_bound_texture_2d == 0, GL_INVALID_OPERATION);
|
||||||
|
|
||||||
// We only support symbolic constants for now
|
// We only support symbolic constants for now
|
||||||
RETURN_WITH_ERROR_IF(!(internal_format == GL_RGB || internal_format == GL_RGBA), GL_INVALID_ENUM);
|
RETURN_WITH_ERROR_IF(!(internal_format == GL_RGB || internal_format == GL_RGBA), GL_INVALID_ENUM);
|
||||||
RETURN_WITH_ERROR_IF(type != GL_UNSIGNED_BYTE, GL_INVALID_VALUE);
|
RETURN_WITH_ERROR_IF(type != GL_UNSIGNED_BYTE, GL_INVALID_VALUE);
|
||||||
|
@ -1226,6 +1237,55 @@ void SoftwareGLContext::gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoftwareGLContext::gl_bind_texture(GLenum target, GLuint texture)
|
||||||
|
{
|
||||||
|
RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
|
||||||
|
// FIXME: We only support GL_TEXTURE_2D for now
|
||||||
|
RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
|
||||||
|
|
||||||
|
if (texture == 0) {
|
||||||
|
switch (target) {
|
||||||
|
case GL_TEXTURE_2D:
|
||||||
|
m_bound_texture_2d = 0;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_allocated_textures.find(texture);
|
||||||
|
|
||||||
|
// The texture name does not exist
|
||||||
|
RETURN_WITH_ERROR_IF(it == m_allocated_textures.end(), GL_INVALID_VALUE);
|
||||||
|
|
||||||
|
auto texture_object = it->value;
|
||||||
|
|
||||||
|
// Binding a texture to a different target than it was first bound is an invalid operation
|
||||||
|
// FIXME: We only support GL_TEXTURE_2D for now
|
||||||
|
RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && !texture_object.is_null() && !texture_object->is_texture_2d(), GL_INVALID_OPERATION);
|
||||||
|
|
||||||
|
if (!texture_object) {
|
||||||
|
// This is the first time the texture is bound. Allocate an actual texture object
|
||||||
|
switch (target) {
|
||||||
|
case GL_TEXTURE_2D:
|
||||||
|
texture_object = adopt_ref(*new Texture2D());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_allocated_textures.set(texture, texture_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
case GL_TEXTURE_2D:
|
||||||
|
m_bound_texture_2d = texture;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SoftwareGLContext::present()
|
void SoftwareGLContext::present()
|
||||||
{
|
{
|
||||||
m_rasterizer.blit_to(*m_frontbuffer);
|
m_rasterizer.blit_to(*m_frontbuffer);
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) override;
|
virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) override;
|
||||||
virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) override;
|
virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) override;
|
||||||
virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) override;
|
virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) override;
|
||||||
|
virtual void gl_bind_texture(GLenum target, GLuint texture) override;
|
||||||
|
|
||||||
virtual void present() override;
|
virtual void present() override;
|
||||||
|
|
||||||
|
@ -128,6 +129,8 @@ private:
|
||||||
|
|
||||||
GLenum m_current_read_buffer = GL_BACK;
|
GLenum m_current_read_buffer = GL_BACK;
|
||||||
|
|
||||||
|
GLuint m_bound_texture_2d = 0;
|
||||||
|
|
||||||
NonnullRefPtr<Gfx::Bitmap> m_frontbuffer;
|
NonnullRefPtr<Gfx::Bitmap> m_frontbuffer;
|
||||||
|
|
||||||
Clipper m_clipper;
|
Clipper m_clipper;
|
||||||
|
|
|
@ -414,6 +414,13 @@ SoftwareRasterizer::SoftwareRasterizer(const Gfx::IntSize& min_size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle)
|
||||||
|
{
|
||||||
|
rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [](const FloatVector2&, const FloatVector4& color) -> FloatVector4 {
|
||||||
|
return color;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Texture2D& texture)
|
void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Texture2D& texture)
|
||||||
{
|
{
|
||||||
rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [&texture](const FloatVector2& uv, const FloatVector4& color) -> FloatVector4 {
|
rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [&texture](const FloatVector2& uv, const FloatVector4& color) -> FloatVector4 {
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
SoftwareRasterizer(const Gfx::IntSize& min_size);
|
SoftwareRasterizer(const Gfx::IntSize& min_size);
|
||||||
|
|
||||||
void submit_triangle(const GLTriangle& triangle, const Texture2D& texture);
|
void submit_triangle(const GLTriangle& triangle, const Texture2D& texture);
|
||||||
|
void submit_triangle(const GLTriangle& triangle);
|
||||||
void resize(const Gfx::IntSize& min_size);
|
void resize(const Gfx::IntSize& min_size);
|
||||||
void clear_color(const FloatVector4&);
|
void clear_color(const FloatVector4&);
|
||||||
void clear_depth(float);
|
void clear_depth(float);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue