autocommit 2022-01-28 19:46:23 CET
This commit is contained in:
parent
a5573b8a3a
commit
b11a36729c
45 changed files with 1646 additions and 2171 deletions
55
src/render/gl/frame_buffer.rs
Normal file
55
src/render/gl/frame_buffer.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use crate::rect::Rect;
|
||||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::gl::render_buffer::GlRenderBuffer;
|
||||
use crate::render::gl::sys::{glDeleteFramebuffers, GLuint};
|
||||
use crate::render::gl::texture::GlTexture;
|
||||
use crate::render::sys::{glDisable, glEnable, glScissor, GL_SCISSOR_TEST};
|
||||
use crate::utils::ptr_ext::PtrExt;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct GlFrameBuffer {
|
||||
pub _rb: Option<Rc<GlRenderBuffer>>,
|
||||
pub _tex: Option<Rc<GlTexture>>,
|
||||
pub ctx: Rc<EglContext>,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub fbo: GLuint,
|
||||
}
|
||||
|
||||
impl Drop for GlFrameBuffer {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.ctx.with_current(|| {
|
||||
unsafe {
|
||||
glDeleteFramebuffers(1, &self.fbo);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn with_scissor<T, F: FnOnce() -> T>(scissor: &Rect, f: F) -> T {
|
||||
#[thread_local]
|
||||
static mut SCISSOR: *const Rect = ptr::null();
|
||||
|
||||
let prev = SCISSOR;
|
||||
if prev.is_null() {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
glScissor(
|
||||
scissor.x1(),
|
||||
scissor.y1(),
|
||||
scissor.width(),
|
||||
scissor.height(),
|
||||
);
|
||||
SCISSOR = scissor;
|
||||
let res = f();
|
||||
if prev.is_null() {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
let prev = prev.deref();
|
||||
glScissor(prev.x1(), prev.y1(), prev.width(), prev.height());
|
||||
}
|
||||
SCISSOR = prev;
|
||||
res
|
||||
}
|
||||
6
src/render/gl/mod.rs
Normal file
6
src/render/gl/mod.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
pub mod frame_buffer;
|
||||
pub mod program;
|
||||
pub mod render_buffer;
|
||||
pub mod shader;
|
||||
pub mod sys;
|
||||
pub mod texture;
|
||||
66
src/render/gl/program.rs
Normal file
66
src/render/gl/program.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::gl::shader::GlShader;
|
||||
use crate::render::gl::sys::{
|
||||
glAttachShader, glCreateProgram, glDeleteProgram, glDetachShader, glGetAttribLocation,
|
||||
glGetProgramiv, glGetUniformLocation, glLinkProgram, GLint, GLuint, GL_FALSE, GL_LINK_STATUS,
|
||||
};
|
||||
use crate::render::gl::sys::{GL_FRAGMENT_SHADER, GL_VERTEX_SHADER};
|
||||
use crate::render::RenderError;
|
||||
use std::rc::Rc;
|
||||
use uapi::Ustr;
|
||||
|
||||
pub struct GlProgram {
|
||||
pub _ctx: Rc<EglContext>,
|
||||
pub prog: GLuint,
|
||||
}
|
||||
|
||||
impl GlProgram {
|
||||
pub unsafe fn from_shaders(
|
||||
ctx: &Rc<EglContext>,
|
||||
vert: &str,
|
||||
frag: &str,
|
||||
) -> Result<Self, RenderError> {
|
||||
let vert = GlShader::compile(ctx, GL_VERTEX_SHADER, vert)?;
|
||||
let frag = GlShader::compile(ctx, GL_FRAGMENT_SHADER, frag)?;
|
||||
Self::link(&vert, &frag)
|
||||
}
|
||||
|
||||
pub unsafe fn link(vert: &GlShader, frag: &GlShader) -> Result<Self, RenderError> {
|
||||
let res = GlProgram {
|
||||
_ctx: vert.ctx.clone(),
|
||||
prog: glCreateProgram(),
|
||||
};
|
||||
glAttachShader(res.prog, vert.shader);
|
||||
glAttachShader(res.prog, frag.shader);
|
||||
glLinkProgram(res.prog);
|
||||
glDetachShader(res.prog, vert.shader);
|
||||
glDetachShader(res.prog, frag.shader);
|
||||
|
||||
let mut ok = 0;
|
||||
glGetProgramiv(res.prog, GL_LINK_STATUS, &mut ok);
|
||||
if ok == GL_FALSE as _ {
|
||||
return Err(RenderError::ProgramLink);
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub unsafe fn get_uniform_location(&self, name: &Ustr) -> GLint {
|
||||
glGetUniformLocation(self.prog, name.as_ptr() as _)
|
||||
}
|
||||
|
||||
pub unsafe fn get_attrib_location(&self, name: &Ustr) -> GLint {
|
||||
glGetAttribLocation(self.prog, name.as_ptr() as _)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GlProgram {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = self._ctx.with_current(|| {
|
||||
glDeleteProgram(self.prog);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/render/gl/render_buffer.rs
Normal file
72
src/render/gl/render_buffer.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::egl::image::EglImage;
|
||||
use crate::render::egl::PROCS;
|
||||
use crate::render::gl::frame_buffer::GlFrameBuffer;
|
||||
use crate::render::gl::sys::{
|
||||
glBindFramebuffer, glBindRenderbuffer, glCheckFramebufferStatus, glDeleteRenderbuffers,
|
||||
glFramebufferRenderbuffer, glGenFramebuffers, glGenRenderbuffers, GLeglImageOES, GLuint,
|
||||
GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE, GL_RENDERBUFFER,
|
||||
};
|
||||
use crate::render::RenderError;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct GlRenderBuffer {
|
||||
pub img: Rc<EglImage>,
|
||||
pub ctx: Rc<EglContext>,
|
||||
rbo: GLuint,
|
||||
}
|
||||
|
||||
impl GlRenderBuffer {
|
||||
pub unsafe fn from_image(
|
||||
img: &Rc<EglImage>,
|
||||
ctx: &Rc<EglContext>,
|
||||
) -> Result<Rc<GlRenderBuffer>, RenderError> {
|
||||
let mut rbo = 0;
|
||||
glGenRenderbuffers(1, &mut rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
PROCS.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, GLeglImageOES(img.img.0));
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
Ok(Rc::new(GlRenderBuffer {
|
||||
img: img.clone(),
|
||||
ctx: ctx.clone(),
|
||||
rbo,
|
||||
}))
|
||||
}
|
||||
|
||||
pub unsafe fn create_framebuffer(self: &Rc<Self>) -> Result<GlFrameBuffer, RenderError> {
|
||||
let mut fbo = 0;
|
||||
glGenFramebuffers(1, &mut fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER,
|
||||
self.rbo,
|
||||
);
|
||||
let status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
let fb = GlFrameBuffer {
|
||||
_rb: Some(self.clone()),
|
||||
_tex: None,
|
||||
ctx: self.ctx.clone(),
|
||||
fbo,
|
||||
width: self.img.width,
|
||||
height: self.img.height,
|
||||
};
|
||||
if status != GL_FRAMEBUFFER_COMPLETE {
|
||||
return Err(RenderError::CreateFramebuffer);
|
||||
}
|
||||
Ok(fb)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GlRenderBuffer {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.ctx.with_current(|| {
|
||||
unsafe {
|
||||
glDeleteRenderbuffers(1, &self.rbo);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
45
src/render/gl/shader.rs
Normal file
45
src/render/gl/shader.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::gl::sys::{
|
||||
glCompileShader, glCreateShader, glDeleteShader, glGetShaderiv, glShaderSource, GLenum, GLuint,
|
||||
GL_COMPILE_STATUS, GL_FALSE,
|
||||
};
|
||||
use crate::render::RenderError;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct GlShader {
|
||||
pub ctx: Rc<EglContext>,
|
||||
pub shader: GLuint,
|
||||
}
|
||||
|
||||
impl GlShader {
|
||||
pub unsafe fn compile(
|
||||
ctx: &Rc<EglContext>,
|
||||
ty: GLenum,
|
||||
src: &str,
|
||||
) -> Result<Self, RenderError> {
|
||||
let shader = glCreateShader(ty);
|
||||
let res = GlShader {
|
||||
ctx: ctx.clone(),
|
||||
shader,
|
||||
};
|
||||
let len = src.len() as _;
|
||||
glShaderSource(shader, 1, &(src.as_ptr() as _), &len);
|
||||
glCompileShader(shader);
|
||||
|
||||
let mut ok = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &mut ok);
|
||||
if ok == GL_FALSE as _ {
|
||||
return Err(RenderError::ShaderCompileFailed);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GlShader {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.ctx.with_current(|| unsafe {
|
||||
glDeleteShader(self.shader);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
131
src/render/gl/sys.rs
Normal file
131
src/render/gl/sys.rs
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
pub use uapi::c;
|
||||
|
||||
pub type GLbitfield = c::c_uint;
|
||||
pub type GLboolean = c::c_uchar;
|
||||
pub type GLchar = c::c_char;
|
||||
pub type GLenum = c::c_uint;
|
||||
pub type GLfloat = f32;
|
||||
pub type GLint = c::c_int;
|
||||
pub type GLsizei = c::c_int;
|
||||
pub type GLubyte = u8;
|
||||
pub type GLuint = c::c_uint;
|
||||
|
||||
egl_transparent!(GLeglImageOES);
|
||||
|
||||
pub const GL_BGRA_EXT: GLint = 0x80E1;
|
||||
pub const GL_CLAMP_TO_EDGE: GLint = 0x812F;
|
||||
pub const GL_COLOR_ATTACHMENT0: GLenum = 0x8CE0;
|
||||
pub const GL_COLOR_BUFFER_BIT: GLbitfield = 0x00004000;
|
||||
pub const GL_COMPILE_STATUS: GLenum = 0x8B81;
|
||||
pub const GL_EXTENSIONS: GLenum = 0x1F03;
|
||||
pub const GL_FALSE: GLboolean = 0;
|
||||
pub const GL_FLOAT: GLenum = 0x1406;
|
||||
pub const GL_FRAGMENT_SHADER: GLenum = 0x8B30;
|
||||
pub const GL_FRAMEBUFFER_COMPLETE: GLenum = 0x8CD5;
|
||||
pub const GL_FRAMEBUFFER: GLenum = 0x8D40;
|
||||
pub const GL_LINEAR: GLint = 0x2601;
|
||||
pub const GL_LINK_STATUS: GLenum = 0x8B82;
|
||||
pub const GL_RENDERBUFFER: GLenum = 0x8D41;
|
||||
pub const GL_SCISSOR_TEST: GLenum = 0x0C11;
|
||||
pub const GL_TEXTURE0: GLenum = 0x84C0;
|
||||
pub const GL_TEXTURE_2D: GLenum = 0x0DE1;
|
||||
pub const GL_TEXTURE_MAG_FILTER: GLenum = 0x2800;
|
||||
pub const GL_TEXTURE_MIN_FILTER: GLenum = 0x2801;
|
||||
pub const GL_TEXTURE_WRAP_S: GLenum = 0x2802;
|
||||
pub const GL_TEXTURE_WRAP_T: GLenum = 0x2803;
|
||||
pub const GL_TRIANGLE_STRIP: GLenum = 0x0005;
|
||||
pub const GL_TRIANGLES: GLenum = 0x0004;
|
||||
pub const GL_UNPACK_ROW_LENGTH_EXT: GLenum = 0x0CF2;
|
||||
pub const GL_UNSIGNED_BYTE: GLint = 0x1401;
|
||||
pub const GL_VERTEX_SHADER: GLenum = 0x8B31;
|
||||
|
||||
#[link(name = "GLESv2")]
|
||||
extern "C" {
|
||||
pub fn glGetString(name: GLenum) -> *const u8;
|
||||
pub fn glGenRenderbuffers(n: GLsizei, renderbuffers: *mut GLuint);
|
||||
pub fn glDeleteRenderbuffers(n: GLsizei, renderbuffers: *const GLuint);
|
||||
pub fn glBindRenderbuffer(target: GLenum, renderbuffer: GLuint);
|
||||
pub fn glGenFramebuffers(n: GLsizei, framebuffers: *mut GLuint);
|
||||
pub fn glDeleteFramebuffers(n: GLsizei, framebuffers: *const GLuint);
|
||||
pub fn glBindFramebuffer(target: GLenum, framebuffer: GLuint);
|
||||
pub fn glFramebufferRenderbuffer(
|
||||
target: GLenum,
|
||||
attachment: GLenum,
|
||||
renderbuffertarget: GLenum,
|
||||
renderbuffer: GLuint,
|
||||
);
|
||||
pub fn glFramebufferTexture2D(
|
||||
target: GLenum,
|
||||
attachment: GLenum,
|
||||
textarget: GLenum,
|
||||
texture: GLenum,
|
||||
level: GLint,
|
||||
);
|
||||
pub fn glCheckFramebufferStatus(target: GLenum) -> GLenum;
|
||||
pub fn glClear(mask: GLbitfield);
|
||||
pub fn glClearColor(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat);
|
||||
pub fn glFlush();
|
||||
|
||||
pub fn glGenTextures(n: GLsizei, textures: *mut GLuint);
|
||||
pub fn glDeleteTextures(n: GLsizei, textures: *const GLuint);
|
||||
pub fn glBindTexture(target: GLenum, texture: GLuint);
|
||||
pub fn glTexParameteri(target: GLenum, pname: GLenum, param: GLint);
|
||||
|
||||
pub fn glPixelStorei(pname: GLenum, param: GLint);
|
||||
|
||||
pub fn glTexImage2D(
|
||||
target: GLenum,
|
||||
level: GLint,
|
||||
internalformat: GLint,
|
||||
width: GLsizei,
|
||||
height: GLsizei,
|
||||
border: GLint,
|
||||
format: GLenum,
|
||||
ty: GLenum,
|
||||
pixels: *const c::c_void,
|
||||
);
|
||||
|
||||
pub fn glScissor(x: GLint, y: GLint, width: GLsizei, height: GLsizei);
|
||||
pub fn glEnable(cap: GLenum);
|
||||
pub fn glDisable(cap: GLenum);
|
||||
pub fn glViewport(x: GLint, y: GLint, width: GLsizei, height: GLsizei);
|
||||
|
||||
pub fn glCreateShader(ty: GLenum) -> GLuint;
|
||||
pub fn glDeleteShader(shader: GLuint);
|
||||
pub fn glShaderSource(
|
||||
shader: GLuint,
|
||||
count: GLsizei,
|
||||
string: *const *const GLchar,
|
||||
length: *const GLint,
|
||||
);
|
||||
pub fn glCompileShader(shader: GLuint);
|
||||
pub fn glGetShaderiv(shader: GLuint, pname: GLenum, params: *mut GLint);
|
||||
|
||||
pub fn glCreateProgram() -> GLuint;
|
||||
pub fn glDeleteProgram(prog: GLuint);
|
||||
pub fn glAttachShader(prog: GLuint, shader: GLuint);
|
||||
pub fn glDetachShader(prog: GLuint, shader: GLuint);
|
||||
pub fn glLinkProgram(prog: GLuint);
|
||||
pub fn glGetProgramiv(program: GLuint, pname: GLenum, params: *mut GLint);
|
||||
pub fn glUseProgram(program: GLuint);
|
||||
|
||||
pub fn glGetUniformLocation(prog: GLuint, name: *const GLchar) -> GLint;
|
||||
pub fn glGetAttribLocation(prog: GLuint, name: *const GLchar) -> GLint;
|
||||
pub fn glUniform1i(location: GLint, v0: GLint);
|
||||
pub fn glUniform1f(location: GLint, v0: GLfloat);
|
||||
pub fn glUniform4f(location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat, v3: GLfloat);
|
||||
pub fn glVertexAttribPointer(
|
||||
index: GLuint,
|
||||
size: GLint,
|
||||
ty: GLenum,
|
||||
normalized: GLboolean,
|
||||
stride: GLsizei,
|
||||
pointer: *const u8,
|
||||
);
|
||||
|
||||
pub fn glActiveTexture(texture: GLuint);
|
||||
|
||||
pub fn glEnableVertexAttribArray(idx: GLuint);
|
||||
pub fn glDisableVertexAttribArray(idx: GLuint);
|
||||
pub fn glDrawArrays(mode: GLenum, first: GLint, count: GLsizei);
|
||||
}
|
||||
138
src/render/gl/texture.rs
Normal file
138
src/render/gl/texture.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
use crate::format::Format;
|
||||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::gl::frame_buffer::GlFrameBuffer;
|
||||
use crate::render::gl::sys::{
|
||||
glBindFramebuffer, glBindTexture, glCheckFramebufferStatus, glDeleteTextures,
|
||||
glFramebufferTexture2D, glGenFramebuffers, glGenTextures, glPixelStorei, glTexImage2D,
|
||||
glTexParameteri, GLint, GLuint, GL_CLAMP_TO_EDGE, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER,
|
||||
GL_FRAMEBUFFER_COMPLETE, GL_LINEAR, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_UNPACK_ROW_LENGTH_EXT,
|
||||
};
|
||||
use crate::render::RenderError;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct GlTexture {
|
||||
pub(super) ctx: Rc<EglContext>,
|
||||
pub tex: GLuint,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
|
||||
impl GlTexture {
|
||||
pub fn new(
|
||||
ctx: &Rc<EglContext>,
|
||||
format: &'static Format,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<Rc<GlTexture>, RenderError> {
|
||||
let tex = ctx.with_current(|| unsafe {
|
||||
let mut tex = 0;
|
||||
glGenTextures(1, &mut tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
format.gl_format,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
format.gl_format as _,
|
||||
format.gl_type as _,
|
||||
ptr::null(),
|
||||
);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
Ok(tex)
|
||||
})?;
|
||||
Ok(Rc::new(GlTexture {
|
||||
ctx: ctx.clone(),
|
||||
tex,
|
||||
width,
|
||||
height,
|
||||
}))
|
||||
}
|
||||
|
||||
pub unsafe fn to_framebuffer(self: &Rc<Self>) -> Result<Rc<GlFrameBuffer>, RenderError> {
|
||||
self.ctx.with_current(|| unsafe {
|
||||
let mut fbo = 0;
|
||||
glGenFramebuffers(1, &mut fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D,
|
||||
self.tex,
|
||||
0,
|
||||
);
|
||||
let fb = GlFrameBuffer {
|
||||
_rb: None,
|
||||
_tex: Some(self.clone()),
|
||||
ctx: self.ctx.clone(),
|
||||
fbo,
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
};
|
||||
let status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
if status != GL_FRAMEBUFFER_COMPLETE {
|
||||
return Err(RenderError::CreateFramebuffer);
|
||||
}
|
||||
Ok(Rc::new(fb))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn import_texture(
|
||||
ctx: &Rc<EglContext>,
|
||||
data: &[Cell<u8>],
|
||||
format: &'static Format,
|
||||
width: i32,
|
||||
height: i32,
|
||||
stride: i32,
|
||||
) -> Result<GlTexture, RenderError> {
|
||||
if (stride * height) as usize > data.len() {
|
||||
return Err(RenderError::SmallImageBuffer);
|
||||
}
|
||||
let tex = ctx.with_current(|| unsafe {
|
||||
let mut tex = 0;
|
||||
glGenTextures(1, &mut tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
format.gl_format,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
format.gl_format as _,
|
||||
format.gl_type as _,
|
||||
data.as_ptr() as _,
|
||||
);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
Ok(tex)
|
||||
})?;
|
||||
Ok(GlTexture {
|
||||
ctx: ctx.clone(),
|
||||
tex,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GlTexture {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.ctx.with_current(|| {
|
||||
glDeleteTextures(1, &self.tex);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue