int S9xGTKDisplayDriver::init (void) { int padding; GtkAllocation allocation; buffer1[0] = malloc (image_padded_size+1024); buffer1[1] = malloc (scaled_padded_size+1024); buffer2[0] = malloc (image_padded_size+1024); buffer2[1] = malloc (scaled_padded_size+1024); padding = (image_padded_size - image_size) / 2+512; padded_buffer1[0] = (void *) (((uint8 *) buffer1[0]) + padding); padded_buffer2[0] = (void *) (((uint8 *) buffer2[0]) + padding); padding = (scaled_padded_size - scaled_size) / 2; padded_buffer1[1] = (void *) (((uint8 *) buffer1[1]) + padding); padded_buffer2[1] = (void *) (((uint8 *) buffer2[1]) + padding); gtk_widget_get_allocation (drawing_area, &allocation); gdk_buffer_width = allocation.width; gdk_buffer_height = allocation.height; padded_buffer1[2] = malloc (gdk_buffer_width * gdk_buffer_height * 3); padded_buffer2[2] = malloc (gdk_buffer_width * gdk_buffer_height * 3); //SSSSSSS pixbuf = gdk_pixbuf_new_from_data ((guchar *) padded_buffer2[2], GDK_COLORSPACE_RGB, FALSE, 8, gdk_buffer_width, gdk_buffer_height, gdk_buffer_width * 3, NULL, NULL); S9xSetEndianess (ENDIAN_MSB); //SSS memset (buffer1[0], 0, image_padded_size); memset (buffer1[1], 0, scaled_padded_size); memset (buffer2[0], 0, image_padded_size); memset (buffer2[1], 0, scaled_padded_size); GFX.Screen1 = (uint16 *) padded_buffer1[0]; GFX.Screen2 = (uint16 *) padded_buffer2[0]; GFX.Pitch = image_width * image_bpp; return 0; }
void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset) { uint8 *final_buffer = NULL; int final_pitch; void *pbo_map = NULL; int x, y, w, h; GtkAllocation allocation; gtk_widget_get_allocation (drawing_area, &allocation); if (output_window_width != allocation.width || output_window_height != allocation.height) { resize (); } #if GTK_CHECK_VERSION(3,10,0) int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window); allocation.width *= gdk_scale_factor; allocation.height *= gdk_scale_factor; #endif if (!legacy) glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, texmap); GLint filter = Settings.BilinearFilter ? GL_LINEAR : GL_NEAREST; glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); GLint clamp = (using_glsl_shaders || !npot) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE; glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp); glClear (GL_COLOR_BUFFER_BIT); if (config->scale_method > 0) { uint8 *src_buffer = (uint8 *) padded_buffer[0]; int src_pitch = image_width * image_bpp; uint8 *dst_buffer; int dst_pitch; src_buffer += (src_pitch * yoffset); dst_buffer = (uint8 *) padded_buffer[1]; dst_pitch = scaled_max_width * image_bpp; final_buffer = (uint8 *) padded_buffer[1]; final_pitch = scaled_max_width * image_bpp; S9xFilter (src_buffer, src_pitch, dst_buffer, dst_pitch, width, height); } else { final_buffer = (uint8 *) padded_buffer[0]; final_pitch = image_width * image_bpp; final_buffer += (final_pitch * yoffset); } x = width; y = height; w = allocation.width; h = allocation.height; S9xApplyAspect (x, y, w, h); glViewport (x, allocation.height - y - h, w, h); window->set_mouseable_area (x, y, w, h); update_texture_size (width, height); if (using_pbos) { if (config->pbo_format == 16) { glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width * height * 2, NULL, GL_STREAM_DRAW); if (version >= 30) pbo_map = glMapBufferRange ( GL_PIXEL_UNPACK_BUFFER, 0, width * height * 2, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT); else pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); for (int y = 0; y < height; y++) { memcpy ((uint8 *) pbo_map + (width * y * 2), final_buffer + (y * final_pitch), width * image_bpp); } glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width); glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } else /* 32-bit color */ { glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_STREAM_DRAW); if (version >= 30) pbo_map = glMapBufferRange ( GL_PIXEL_UNPACK_BUFFER, 0, width * height * 4, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT); else pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); /* Pixel swizzling in software */ S9xSetEndianess (ENDIAN_NORMAL); S9xConvert (final_buffer, pbo_map, final_pitch, width * 4, width, height, 32); glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width); glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } } else { glPixelStorei (GL_UNPACK_ROW_LENGTH, final_pitch / image_bpp); glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, final_buffer); } if (using_glsl_shaders) { glsl_shader->render (texmap, width, height, x, allocation.height - y - h, w, h, S9xViewportCallback); swap_buffers (); return; } glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); swap_buffers (); }
void S9xOpenGLDisplayDriver::update (int width, int height) { GLint filter; uint8 *final_buffer = NULL; int final_pitch; void *pboMemory = NULL; int x, y, w, h; if (width <= 0) { gdk_window_hide (gdk_window); return; } GtkAllocation allocation; gtk_widget_get_allocation (drawing_area, &allocation); if (output_window_width != allocation.width || output_window_height != allocation.height) { resize_window (allocation.width, allocation.height); } /* This avoids messing with the texture parameters every time */ if (config->bilinear_filter != filtering) { filter = config->bilinear_filter ? GL_LINEAR : GL_NEAREST; glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); filtering = config->bilinear_filter; } glClear (GL_COLOR_BUFFER_BIT); glEnable (tex_target); if (config->scale_method > 0) { uint8 *src_buffer = (uint8 *) padded_buffer[0]; int src_pitch = image_width * image_bpp; uint8 *dst_buffer; int dst_pitch; dst_buffer = (uint8 *) padded_buffer[1]; dst_pitch = scaled_max_width * image_bpp; final_buffer = (uint8 *) padded_buffer[1]; final_pitch = scaled_max_width * image_bpp; S9xFilter (src_buffer, src_pitch, dst_buffer, dst_pitch, width, height); } else { final_buffer = (uint8 *) padded_buffer[0]; final_pitch = image_width * image_bpp; } x = width; y = height; w = allocation.width; h = allocation.height; S9xApplyAspect (x, y, w, h); glViewport (x, y, w, h); window->set_mouseable_area (x, y, w, h); update_texture_size (width, height); if (using_pbos) { if (config->pbo_format == PBO_FMT_16) { glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width * height * 2, NULL, GL_STREAM_DRAW); pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); for (int y = 0; y < height; y++) { memcpy ((uint8 *) pboMemory + (width * y * 2), final_buffer + (y * final_pitch), width * image_bpp); } glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } else if (config->pbo_format == PBO_FMT_24) { /* Complement width to next multiple of 4 to force line size to * be a multiple of 4 bytes. Otherwise, packing fails. */ int width_mul_4 = width + ((4 - (width % 4)) % 4); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width_mul_4 * height * 3, NULL, GL_STREAM_DRAW); pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); /* Pixel swizzling in software */ S9xSetEndianess (ENDIAN_MSB); S9xConvert (final_buffer, pboMemory, final_pitch, width_mul_4 * 3, width, height, 24); glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width_mul_4); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } else /* PBO_FMT_32 */ { glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_STREAM_DRAW); pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); /* Pixel swizzling in software */ #ifdef __BIG_ENDIAN__ S9xSetEndianess (ENDIAN_MSB); #else S9xSetEndianess (ENDIAN_LSB); #endif S9xConvert (final_buffer, pboMemory, final_pitch, width * 4, width, height, 32); glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_BGRA, PBO_BGRA_NATIVE_ORDER, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } } else { glPixelStorei (GL_UNPACK_ROW_LENGTH, final_pitch / image_bpp); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, final_buffer); } if (tex_target == GL_TEXTURE_2D) { texcoords[1] = (float) (height) / texture_height; texcoords[2] = (float) (width) / texture_width; texcoords[3] = texcoords[1]; texcoords[4] = texcoords[2]; } else if (tex_target == GL_TEXTURE_RECTANGLE) { texcoords[1] = (float) (height); texcoords[2] = (float) (width); texcoords[3] = texcoords[1]; texcoords[4] = texcoords[2]; } if (using_shaders) { GLint location; float inputSize[2] = { width, height }; location = glGetUniformLocation (program, "rubyInputSize"); glUniform2fv (location, 1, inputSize); float outputSize[2] = {w , h }; location = glGetUniformLocation (program, "rubyOutputSize"); glUniform2fv (location, 1, outputSize); float textureSize[2] = { texture_width, texture_height }; location = glGetUniformLocation (program, "rubyTextureSize"); glUniform2fv (location, 1, textureSize); } glDrawArrays (GL_QUADS, 0, 4); gl_swap (); return; }
int S9xXVDisplayDriver::init (void) { int padding; int depth = 0, num_formats, num_attrs, highest_formats = 0; XvImageFormatValues *formats = NULL; XvAdaptorInfo *adaptors; XvAttribute *port_attr; VisualID visualid = None; unsigned int num_adaptors; GdkScreen *screen; GdkWindow *root; buffer[0] = malloc (image_padded_size); buffer[1] = malloc (scaled_padded_size); padding = (image_padded_size - image_size) / 2; padded_buffer[0] = (void *) (((uint8 *) buffer[0]) + padding); padding = (scaled_padded_size - scaled_size) / 2; padded_buffer[1] = (void *) (((uint8 *) buffer[1]) + padding); memset (buffer[0], 0, image_padded_size); memset (buffer[1], 0, scaled_padded_size); /* Setup XV */ gtk_widget_realize (drawing_area); display = gdk_x11_drawable_get_xdisplay (GDK_DRAWABLE (gtk_widget_get_window (drawing_area))); screen = gtk_widget_get_screen (drawing_area); root = gdk_screen_get_root_window (screen); xv_portid = -1; XvQueryAdaptors (display, GDK_WINDOW_XWINDOW (root), &num_adaptors, &adaptors); for (int i = 0; i < (int) num_adaptors; i++) { if (adaptors[i].type & XvInputMask && adaptors[i].type & XvImageMask) { formats = XvListImageFormats (display, adaptors[i].base_id, &num_formats); if (num_formats > highest_formats) { xv_portid = adaptors[i].base_id; highest_formats = num_formats; visualid = adaptors[i].formats->visual_id; } free (formats); } } XvFreeAdaptorInfo (adaptors); if (xv_portid < 0) { fprintf (stderr, "Could not open Xv output port.\n"); return -1; } /* Set XV_AUTOPAINT_COLORKEY _only_ if available */ port_attr = XvQueryPortAttributes (display, xv_portid, &num_attrs); for (int i = 0; i < num_attrs; i++) { if (!strcmp (port_attr[i].name, "XV_AUTOPAINT_COLORKEY")) { Atom colorkey = None; colorkey = XInternAtom (display, "XV_AUTOPAINT_COLORKEY", True); if (colorkey != None) XvSetPortAttribute (display, xv_portid, colorkey, 1); } } /* Try to find an RGB format */ format = FOURCC_YUY2; bpp = 100; formats = XvListImageFormats (display, xv_portid, &num_formats); for (int i = 0; i < num_formats; i++) { if (formats[i].id == 0x3 || formats[i].type == XvRGB) { if (formats[i].bits_per_pixel < bpp) { format = formats[i].id; bpp = formats[i].bits_per_pixel; bytes_per_pixel = (bpp == 15) ? 2 : bpp >> 3; depth = formats[i].depth; this->rshift = get_inv_shift (formats[i].red_mask, bpp); this->gshift = get_inv_shift (formats[i].green_mask, bpp); this->bshift = get_inv_shift (formats[i].blue_mask, bpp); /* Check for red-blue inversion on SiliconMotion drivers */ if (formats[i].red_mask == 0x001f && formats[i].blue_mask == 0x7c00) { int copy = this->rshift; this->rshift = this->bshift; this->bshift = copy; } /* on big-endian Xv still seems to like LSB order */ if (config->force_inverted_byte_order) S9xSetEndianess (ENDIAN_MSB); else S9xSetEndianess (ENDIAN_LSB); } } }
void S9xOpenGLDisplayDriver::update (int width, int height) { GLint filter; uint8 *final_buffer = NULL; uint8 *final_buffer2 = NULL; int combined_pitch; int c_width, c_height; void *pboMemory = NULL; c_width = drawing_area->allocation.width; c_height = drawing_area->allocation.height; if (width <= 0) return; gl_lock (); /* This avoids messing with the texture parameters every time */ if (config->bilinear_filter != filtering) { filter = config->bilinear_filter ? GL_LINEAR : GL_NEAREST; glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); filtering = config->bilinear_filter; } glClear (GL_COLOR_BUFFER_BIT); glEnable (tex_target); if (config->scale_method > 0) { /*uint8 *src_buffer = (uint8 *) padded_buffer[0]; int src_pitch = image_width * image_bpp; uint8 *dst_buffer; int dst_pitch; dst_buffer = (uint8 *) padded_buffer[1]; dst_pitch = scaled_max_width * image_bpp; final_buffer = (uint8 *) padded_buffer[1]; combined_pitch = scaled_max_width * image_bpp; S9xFilter (src_buffer, src_pitch, dst_buffer, dst_pitch, width, height); src_buffer = (uint8 *) padded_buffer[2]; dst_buffer = (uint8 *) padded_buffer[3]; dst_pitch = scaled_max_width * image_bpp; final_buffer2 = (uint8 *) padded_buffer[3]; S9xFilter (src_buffer, src_pitch, dst_buffer, dst_pitch, width, height); combine_buffers((uint16*)combined_buffer, (uint16*)final_buffer, (uint16*)final_buffer2, scaled_max_width, scaled_max_height, image_bpp); */ uint8 *src_buffer = (uint8 *) padded_buffer[0]; int src_pitch = image_width * image_bpp; uint8 *dst_buffer; int dst_pitch; combine_buffers((uint16*)padded_buffer[0], (uint16*)padded_buffer[0], (uint16*)padded_buffer[2], image_width, image_height, image_bpp); dst_buffer = (uint8 *) padded_buffer[1]; dst_pitch = scaled_max_width * image_bpp; final_buffer = (uint8 *) padded_buffer[1]; combined_pitch = scaled_max_width * image_bpp; S9xFilter (src_buffer, src_pitch, dst_buffer, dst_pitch, width, height); memcpy(combined_buffer, dst_buffer, scaled_max_width * scaled_max_height * image_bpp); } else { final_buffer = (uint8 *) padded_buffer[0]; final_buffer2 = (uint8 *) padded_buffer[2]; combined_pitch = image_width * image_bpp; combine_buffers((uint16*)combined_buffer, (uint16*)final_buffer, (uint16*)final_buffer2, image_width, image_height, image_bpp); } double screen_aspect = (double) c_width / (double) c_height; double snes_aspect = S9xGetAspect (); double granularity = 1.0 / (double) MAX (c_width, c_height); if (!config->scale_to_fit) { glViewport ((c_width - width) / 2, (c_height - height) / 2, width, height); window->set_mouseable_area ((c_width - width) / 2, (c_height - height) / 2, width, height); } else if (config->maintain_aspect_ratio && !(screen_aspect <= snes_aspect * (1.0 + granularity) && screen_aspect >= snes_aspect * (1.0 - granularity))) { if (screen_aspect > snes_aspect) { glViewport ((c_width - (int)(c_height * snes_aspect)) / 2, 0, (int)(c_height * snes_aspect), c_height); window->set_mouseable_area ((c_width - (int) (c_height * snes_aspect)) / 2, 0, (int) (c_height * snes_aspect), c_height); } else { glViewport (0, (c_height - (int) (c_width / snes_aspect)) / 2, c_width, (int) (c_width / snes_aspect)); window->set_mouseable_area (0, (c_height - (int) (c_width / snes_aspect)) / 2, c_width, (int) (c_width / snes_aspect)); } } else { glViewport (0, 0, c_width, c_height); window->set_mouseable_area (0, 0, c_width, c_height); } if (width > 0 && height > 0) { update_texture_size (width, height); if (using_pbos) { if (config->pbo_format == PBO_FMT_16) { glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width * height * 2, NULL, GL_STREAM_DRAW); pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); for (int y = 0; y < height; y++) { memcpy ((uint8 *) pboMemory + (width * y * 2), // TODO MIKEL I accidentally deleted the pointer cast here... // I should double check that it's correct, but it should be ok (uint8 *)combined_buffer + (y * combined_pitch), width * image_bpp); } glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } else if (config->pbo_format == PBO_FMT_24) { /* Complement width to next multiple of 4 to force line size to * be a multiple of 4 bytes. Otherwise, packing fails. */ int width_mul_4 = width + ((4 - (width % 4)) % 4); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width_mul_4 * height * 3, NULL, GL_STREAM_DRAW); pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); /* Pixel swizzling in software */ S9xSetEndianess (ENDIAN_MSB); S9xConvert (combined_buffer, pboMemory, combined_pitch, width_mul_4 * 3, width, height, 24); glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width_mul_4); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } else /* PBO_FMT_32 */ { glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData (GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_STREAM_DRAW); pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); /* Pixel swizzling in software */ #ifdef __BIG_ENDIAN__ S9xSetEndianess (ENDIAN_MSB); #else S9xSetEndianess (ENDIAN_LSB); #endif S9xConvert (combined_buffer, pboMemory, combined_pitch, width * 4, width, height, 32); glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); glPixelStorei (GL_UNPACK_ROW_LENGTH, width); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_BGRA, PBO_BGRA_NATIVE_ORDER, BUFFER_OFFSET (0)); glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); } } else { glPixelStorei (GL_UNPACK_ROW_LENGTH, combined_pitch / image_bpp); glTexSubImage2D (tex_target, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, combined_buffer); } if (tex_target == GL_TEXTURE_2D) { texcoords[1] = (float) (height) / texture_height; texcoords[2] = (float) (width) / texture_width; texcoords[3] = texcoords[1]; texcoords[4] = texcoords[2]; } else if (tex_target == GL_TEXTURE_RECTANGLE) { texcoords[1] = (float) (height); texcoords[2] = (float) (width); texcoords[3] = texcoords[1]; texcoords[4] = texcoords[2]; } glDrawArrays (GL_QUADS, 0, 4); } gl_unlock (); gl_swap (); return; }