+/**
+ * Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a
+ * MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer.
+ */
+static void
+fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address2d(unpack, pixels, width,
+ height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0);
+ const GLint srcRowStride = _mesa_image_row_stride(unpack, width,
+ GL_RGB, GL_UNSIGNED_BYTE);
+ GLint i, j;
+ GLubyte *dst;
+ GLint dstRowStride;
+
+ ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
+ GL_MAP_WRITE_BIT, &dst, &dstRowStride);
+
+ if (!dst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+ return;
+ }
+
+ if (ctx->Pixel.ZoomY == -1.0f) {
+ dst = dst + (height - 1) * dstRowStride;
+ dstRowStride = -dstRowStride;
+ }
+
+ for (i = 0; i < height; i++) {
+ GLuint *dst4 = (GLuint *) dst;
+ for (j = 0; j < width; j++) {
+ dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]);
+ }
+ dst += dstRowStride;
+ src += srcRowStride;
+ }
+
+ ctx->Driver.UnmapRenderbuffer(ctx, rb);
+}
+
+
+/**
+ * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a
+ * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer.
+ */
+static void
+fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address2d(unpack, pixels, width,
+ height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
+ const GLint srcRowStride =
+ _mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE);
+ GLint i, j;
+ GLubyte *dst;
+ GLint dstRowStride;
+
+ ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
+ GL_MAP_WRITE_BIT, &dst, &dstRowStride);
+
+ if (!dst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+ return;
+ }
+
+ if (ctx->Pixel.ZoomY == -1.0f) {
+ dst = dst + (height - 1) * dstRowStride;
+ dstRowStride = -dstRowStride;
+ }
+
+ for (i = 0; i < height; i++) {
+ GLuint *dst4 = (GLuint *) dst;
+ for (j = 0; j < width; j++) {
+ dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0],
+ src[j*4+1], src[j*4+2]);
+ }
+ dst += dstRowStride;
+ src += srcRowStride;
+ }
+
+ ctx->Driver.UnmapRenderbuffer(ctx, rb);
+}
+
+
+/**
+ * Handle a common case of drawing a format/type combination that
+ * exactly matches the renderbuffer format.
+ */
+static void
+fast_draw_generic_pixels(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address2d(unpack, pixels, width,
+ height, format, type, 0, 0);
+ const GLint srcRowStride =
+ _mesa_image_row_stride(unpack, width, format, type);
+ const GLint rowLength = width * _mesa_get_format_bytes(rb->Format);
+ GLint i;
+ GLubyte *dst;
+ GLint dstRowStride;
+
+ ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
+ GL_MAP_WRITE_BIT, &dst, &dstRowStride);
+
+ if (!dst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+ return;
+ }
+
+ if (ctx->Pixel.ZoomY == -1.0f) {
+ dst = dst + (height - 1) * dstRowStride;
+ dstRowStride = -dstRowStride;
+ }
+
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, rowLength);
+ dst += dstRowStride;
+ src += srcRowStride;
+ }
+
+ ctx->Driver.UnmapRenderbuffer(ctx, rb);
+}
+