void GL1TextureProvider::copy_image_from( int x, int y, int width, int height, int level, TextureFormat texture_format, GraphicContextProvider *gc) { throw_if_disposed(); OpenGL::set_active(static_cast<GL1GraphicContextProvider*>(gc)); GL1TextureStateTracker state_tracker(texture_type, handle); GLint gl_internal_format; GLenum gl_pixel_format; to_opengl_textureformat(texture_format, gl_internal_format, gl_pixel_format); glCopyTexImage2D( GL_TEXTURE_2D, level, gl_internal_format, x, y, width, height, 0); }
void GL1TextureProvider::set_wrap_mode( TextureWrapMode wrap_s) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, OpenGL::to_enum(wrap_s)); }
PixelBuffer GL1TextureProvider::get_pixeldata(GraphicContext &gc, TextureFormat texture_format, int level) const { throw_if_disposed(); OpenGL::set_active(gc); GL1TextureStateTracker state_tracker(texture_type, handle); GLenum gl_format = 0, gl_type = 0; bool supported = to_opengl_pixelformat(texture_format, gl_format, gl_type); if (supported) { PixelBuffer buffer(pot_width, pot_height, texture_format); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, buffer.get_pitch() / buffer.get_bytes_per_pixel()); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif glGetTexImage(texture_type, level, gl_format, gl_type, buffer.get_data()); return buffer.copy(Rect(0,0, width, height)); } else { PixelBuffer buffer(pot_width, pot_height, tf_rgba8); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, buffer.get_pitch() / buffer.get_bytes_per_pixel()); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif glGetTexImage(texture_type, level, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get_data()); return buffer.copy(Rect(0,0, width, height)).to_format(texture_format); } }
void GL1TextureProvider::set_texture_compare(TextureCompareMode mode, CompareFunction func) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); glTexParameteri(texture_type, GL_TEXTURE_COMPARE_MODE, OpenGL::to_enum(mode)); glTexParameteri(texture_type, GL_TEXTURE_COMPARE_FUNC, OpenGL::to_enum(func)); }
void CL_OpenGLProgramObjectProvider::set_uniform1i(const CL_StringRef &name, int p1) { throw_if_disposed(); CL_ProgramObjectStateTracker state_tracker(handle); int loc = get_uniform_location(name); if (loc == -1) return; glUniform1i(loc, p1); }
void GL3ProgramObjectProvider::set_uniform4f(int location, float v1, float v2, float v3, float v4) { throw_if_disposed(); if (location >= 0) { ProgramObjectStateTracker state_tracker(handle); glUniform4f(location, v1, v2, v3, v4); } }
void GL3ProgramObjectProvider::set_uniform3i(int location, int v1, int v2, int v3) { throw_if_disposed(); if (location >= 0) { ProgramObjectStateTracker state_tracker(handle); glUniform3i(location, v1, v2, v3); } }
void GL3ProgramObjectProvider::set_uniform_matrix(int location, int size, int count, bool transpose, const float *data) { throw_if_disposed(); if (location >= 0) { ProgramObjectStateTracker state_tracker(handle); if( size == 2 ) glUniformMatrix2fv(location, count, transpose, data); else if( size == 3 ) glUniformMatrix3fv(location, count, transpose, data); else if( size == 4 ) glUniformMatrix4fv(location, count, transpose, data); } }
void GL3ProgramObjectProvider::set_uniformfv(int location, int size, int count, const float *data) { throw_if_disposed(); if (location >= 0) { ProgramObjectStateTracker state_tracker(handle); if( size == 1 ) glUniform1fv(location, count, data); else if( size == 2 ) glUniform2fv(location, count, data); else if( size == 3 ) glUniform3fv(location, count, data); else if( size == 4 ) glUniform4fv(location, count, data); } }
void CL_OpenGLProgramObjectProvider::set_uniform_matrix(const CL_StringRef &name, int size, int count, bool transpose, float *data) { throw_if_disposed(); CL_ProgramObjectStateTracker state_tracker(handle); int loc = get_uniform_location(name); if (loc == -1) return; if( size == 2 ) glUniformMatrix2fv(loc, count, transpose, data); else if( size == 3 ) glUniformMatrix3fv(loc, count, transpose, data); else if( size == 4 ) glUniformMatrix4fv(loc, count, transpose, data); else throw CL_Exception(cl_format("Unsupported size given to uniform '%1'.", name)); }
GL1TextureProvider::GL1TextureProvider(TextureDimensions texture_dimensions) : width(0), height(0), depth(0), handle(0), texture_type(0) { SharedGCData::add_disposable(this); switch (texture_dimensions) { case texture_1d: #ifdef __ANDROID__ throw Exception("GL_TEXTURE_1D is not supported"); #else texture_type = GL_TEXTURE_1D; #endif break; case texture_2d: default: texture_type = GL_TEXTURE_2D; break; case texture_3d: texture_type = GL_TEXTURE_3D; break; case texture_cube: #ifdef __ANDROID__ throw Exception("GL_TEXTURE_CUBE_MAP is not supported"); #else texture_type = GL_TEXTURE_CUBE_MAP; #endif break; } OpenGL::set_active(); glGenTextures(1, &handle); GL1TextureStateTracker state_tracker(texture_type, 0); glBindTexture(texture_type, handle); glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); #ifndef __ANDROID__ if (texture_type != GL_TEXTURE_1D) #endif { glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } if (texture_type == GL_TEXTURE_3D) glTexParameteri(texture_type, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); }
void GL1TextureProvider::copy_subimage_from( int offset_x, int offset_y, int x, int y, int width, int height, int level, GraphicContextProvider *gc) { throw_if_disposed(); OpenGL::set_active(static_cast<GL1GraphicContextProvider*>(gc)); GL1TextureStateTracker state_tracker(texture_type, handle); glCopyTexSubImage2D( GL_TEXTURE_2D, level, offset_x, offset_y, x, y, width, height ); }
void GL1TextureProvider::set_max_lod(double max_lod) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); glTexParameterf(texture_type, GL_TEXTURE_MAX_LOD, (GLfloat)max_lod); }
void GL1TextureProvider::create(int new_width, int new_height, int new_depth, int array_size, TextureFormat texture_format, int levels) { throw_if_disposed(); GLint gl_internal_format; GLenum gl_pixel_format; to_opengl_textureformat(texture_format, gl_internal_format, gl_pixel_format); if ( (new_width > 32768) || (new_width < 1) ) { throw Exception("Invalid texture width in the GL1 target"); } if ( (texture_type == GL_TEXTURE_2D) || (texture_type == GL_TEXTURE_3D) ) { if ( (new_height > 32768) || (new_height < 1) ) { throw Exception("Invalid texture height in the GL1 target"); } } if ( texture_type == GL_TEXTURE_3D ) { if ( (new_depth > 32768) || (new_depth < 1) ) { throw Exception("Invalid texture depth in the GL1 target"); } } width = new_width; height = new_height; depth = new_depth; GL1TextureStateTracker state_tracker(texture_type, handle); #ifndef __ANDROID__ if (texture_type == GL_TEXTURE_1D) { pot_width = get_next_power_of_two(new_width); if (pot_width == new_width) { power_of_two_texture=true; } else { power_of_two_texture=false; } pot_ratio_width = (float) width / pot_width; glTexImage1D( GL_TEXTURE_1D, // target 0, // level gl_internal_format, // internalformat pot_width, // width 0, // border gl_pixel_format, // format GL_UNSIGNED_BYTE, // type (it really doesn't matter since nothing is uploaded) nullptr); // texels (0 to avoid uploading) } #endif if (texture_type == GL_TEXTURE_2D) { pot_width = get_next_power_of_two(new_width); pot_height = get_next_power_of_two(new_height); if ( (pot_width == new_width) && (pot_height == new_height)) { power_of_two_texture=true; } else { power_of_two_texture=false; } pot_ratio_width = (float) width / pot_width; pot_ratio_height = (float) height / pot_height; glTexImage2D( GL_TEXTURE_2D, // target 0, // level gl_internal_format, // internalformat pot_width, // width pot_height, // height 0, // border gl_pixel_format, // format GL_UNSIGNED_BYTE, // type (it really doesn't matter since nothing is uploaded) nullptr); // texels (0 to avoid uploading) // Clear the whole texture if it is npot if (!power_of_two_texture) { PixelBuffer image = PixelBuffer(pot_width, pot_height, tf_rgba8); void *data = image.get_data(); memset(data, 0, pot_width * pot_height * 4); GLenum format; GLenum type; to_opengl_pixelformat(image, format, type); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const int bytesPerPixel = image.get_bytes_per_pixel(); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, image.get_pitch() / bytesPerPixel); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif glTexImage2D( GL_TEXTURE_2D, // target 0, // level gl_internal_format, // internalformat pot_width, // width pot_height, // height 0, // border format, // format type, // type data); // texels } } else { pot_width = get_next_power_of_two(new_width); pot_height = get_next_power_of_two(new_height); pot_depth = get_next_power_of_two(new_depth); pot_ratio_width = (float) width / pot_width; pot_ratio_height = (float) height / pot_height; pot_ratio_depth = (float) depth / pot_depth; if ( (pot_width == new_width) && (pot_height == new_height) && (pot_depth == new_depth)) { power_of_two_texture=true; } else { power_of_two_texture=false; } glTexImage3D( GL_TEXTURE_3D, // target 0, // level gl_internal_format, // internalformat pot_width, // width pot_height, // height pot_depth, // depth 0, // border gl_pixel_format, // format GL_UNSIGNED_BYTE, // type (it really doesn't matter since nothing is uploaded) nullptr); // texels (0 to avoid uploading) } }
void GL1TextureProvider::set_texture_image3d( GLuint target, PixelBuffer &image, int image_depth, int level) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); GLint gl_internal_format; GLenum gl_pixel_format; to_opengl_textureformat(image.get_format(), gl_internal_format, gl_pixel_format); // check out if the original texture needs or doesn't need an alpha channel bool needs_alpha = image.has_transparency(); GLenum format; GLenum type; bool conv_needed = !to_opengl_pixelformat(image, format, type); // also check for the pitch (GL1 can only skip pixels, not bytes) if (!conv_needed) { const int bytesPerPixel = image.get_bytes_per_pixel(); if (image.get_pitch() % bytesPerPixel != 0) conv_needed = true; } // no conversion needed if (!conv_needed) { // Upload to GL1: // change alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const int bytesPerPixel = image.get_bytes_per_pixel(); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, image.get_pitch() / bytesPerPixel); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif char *data = (char *) image.get_data(); int image_width = image.get_width(); int image_height = image.get_height() / image_depth; glTexImage3D( target, // target level, // level gl_internal_format, // internalformat image_width, // width image_height, // height image_depth, // depth 0, // border format, // format type, // type data); // texels } // conversion needed else { bool big_endian = Endian::is_system_big(); PixelBuffer buffer( image.get_width(), image.get_height(), needs_alpha ? tf_rgba8 : tf_rgb8); buffer.set_image(image); format = needs_alpha ? GL_RGBA : GL_RGB; // Upload to OpenGL: // change alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const int bytesPerPixel = buffer.get_bytes_per_pixel(); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, buffer.get_pitch() / bytesPerPixel); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif int image_width = image.get_width(); int image_height = image.get_height() / image_depth; // upload glTexImage3D( target, // target level, // level gl_internal_format, // internalformat image_width, // width image_height, // height image_depth, // depth 0, // border format, // format GL_UNSIGNED_BYTE, // type buffer.get_data()); // texels } }
void GL1TextureProvider::set_texture_image2d( GLuint target, PixelBuffer &image, int level) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); GLint gl_internal_format; GLenum gl_pixel_format; to_opengl_textureformat(image.get_format(), gl_internal_format, gl_pixel_format); /* GL_UNPACK_SWAP_BYTES GL_UNPACK_LSB_FIRST GL_UNPACK_SKIP_ROWS GL_UNPACK_SKIP_PIXELS GL_UNPACK_ROW_LENGTH GL_UNPACK_ALIGNMENT GL_UNPACK_IMAGE_HEIGHT GL_UNPACK_SKIP_IMAGES */ // check out if the original texture needs or doesn't need an alpha channel bool needs_alpha = image.has_transparency(); GLenum format; GLenum type; bool conv_needed = !to_opengl_pixelformat(image, format, type); // also check for the pitch (GL1 can only skip pixels, not bytes) if (!conv_needed) { const int bytesPerPixel = image.get_bytes_per_pixel(); if (image.get_pitch() % bytesPerPixel != 0) conv_needed = true; } // no conversion needed if (!conv_needed) { // Upload to GL1: // change alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const int bytesPerPixel = image.get_bytes_per_pixel(); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, image.get_pitch() / bytesPerPixel); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif char *data = (char *) image.get_data(); int image_width = image.get_width(); int image_height = image.get_height(); /* int image_width = 1; int image_height = 1; while (image_width < image.get_width()) image_width *= 2; while (image_height < image.get_height()) image_height *= 2; */ glTexImage2D( target, // target level, // level gl_internal_format, // internalformat image_width, // width image_height, // height 0, // border format, // format type, // type data); // texels } // conversion needed else { bool big_endian = Endian::is_system_big(); PixelBuffer buffer( image.get_width(), image.get_height(), needs_alpha ? tf_rgba8 : tf_rgb8); buffer.set_image(image); format = needs_alpha ? GL_RGBA : GL_RGB; // Upload to OpenGL: // change alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const int bytesPerPixel = buffer.get_bytes_per_pixel(); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, buffer.get_pitch() / bytesPerPixel); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif // upload glTexImage2D( target, // target level, // level gl_internal_format, // internalformat image.get_width(), // width image.get_height(), // height 0, // border format, // format GL_UNSIGNED_BYTE, // type buffer.get_data()); // texels /* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); */ } }
void GL1TextureProvider::copy_from(GraphicContext &gc, int x, int y, int slice, int level, const PixelBuffer &ximage, const Rect &src_rect) { OpenGL::set_active(gc); PixelBuffer image = ximage; if (src_rect.left < 0 || src_rect.top < 0 || src_rect.right > image.get_width() || src_rect.bottom > image.get_height()) throw Exception("Rectangle out of bounds"); throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); // check out if the original texture needs or doesn't need an alpha channel bool needs_alpha = image.has_transparency(); GLenum format; GLenum type; bool conv_needed = !to_opengl_pixelformat(image, format, type); // also check for the pitch (GL1 can only skip pixels, not bytes) if (!conv_needed) { const int bytesPerPixel = image.get_bytes_per_pixel(); if (image.get_pitch() % bytesPerPixel != 0) conv_needed = true; } // no conversion needed if (!conv_needed) { // change alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const int bytesPerPixel = image.get_bytes_per_pixel(); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, image.get_pitch() / bytesPerPixel); glPixelStorei(GL_UNPACK_SKIP_PIXELS, src_rect.left); glPixelStorei(GL_UNPACK_SKIP_ROWS, src_rect.top); #endif } // conversion needed else { bool big_endian = Endian::is_system_big(); PixelBuffer buffer( src_rect.get_width(), src_rect.get_height(), needs_alpha ? tf_rgba8 : tf_rgb8); buffer.set_subimage(image, Point(0, 0), src_rect); format = needs_alpha ? GL_RGBA : GL_RGB; // Upload to GL1: glBindTexture(GL_TEXTURE_2D, handle); // change alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const int bytesPerPixel = buffer.get_bytes_per_pixel(); #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_ROW_LENGTH, buffer.get_pitch() / bytesPerPixel); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif type = GL_UNSIGNED_BYTE; image = buffer; } // upload glTexSubImage2D( GL_TEXTURE_2D, // target level, // level x, y, // xoffset, yoffset src_rect.get_width(), // width src_rect.get_height(), // height format, // format type, // type image.get_data()); // texels if (!power_of_two_texture) { // TODO: This needs corrected.It should be optimised and currently it does not write to the lower right quadrant // Check extend the right edge int right_edge = x + image.get_width(); if ( right_edge >= width ) { char *edge_data = (char *) image.get_data(); edge_data += image.get_bytes_per_pixel() * (width-1); for(int edge_cnt = right_edge; edge_cnt < pot_width; edge_cnt++) { glTexSubImage2D( GL_TEXTURE_2D, // target level, // level edge_cnt, y, // xoffset, yoffset 1, // width src_rect.get_height(), // height format, // format type, // type edge_data); // texels } } // Check extend the bottom edge int bottom_edge = y + image.get_height(); if ( bottom_edge >= height ) { char *edge_data = (char *) image.get_data(); edge_data += image.get_pitch() * (height-1); for(int edge_cnt = bottom_edge; edge_cnt < pot_height; edge_cnt++) { glTexSubImage2D( GL_TEXTURE_2D, // target level, // level x, edge_cnt, // xoffset, yoffset src_rect.get_width(), // width 1, // height format, // format type, // type edge_data); // texels } } } // Restore these unpack values to the default #ifndef __ANDROID__ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); #endif }
void GL1TextureProvider::set_mag_filter(TextureFilter filter) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, OpenGL::to_enum(filter)); }
void GL1TextureProvider::set_max_level(int max_level) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); glTexParameteri(texture_type, GL_TEXTURE_MAX_LEVEL, max_level); }
void GL1TextureProvider::set_lod_bias(double lod_bias) { throw_if_disposed(); GL1TextureStateTracker state_tracker(texture_type, handle); glTexParameterf(texture_type, GL_TEXTURE_LOD_BIAS, (GLfloat)lod_bias); }