+ ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
+ type );
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ if (ctx->Current.RasterPosValid) {
+ FLUSH_CURRENT( ctx, 0 );
+ FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterIndex,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ }
+ else if (ctx->RenderMode == GL_SELECT) {
+ _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+}
+
+#endif
+
+
+
+void GLAPIENTRY
+_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glReadPixels(width=%d height=%d)", width, height );
+ return;
+ }
+
+ if (!pixels) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ ctx->Driver.ReadPixels(ctx, x, y, width, height,
+ format, type, &ctx->Pack, pixels);
+}
+
+
+
+
+
+void GLAPIENTRY
+_mesa_Bitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
+ return;
+ }
+
+ if (ctx->Current.RasterPosValid == GL_FALSE) {
+ return; /* do nothing */
+ }
+
+ if (ctx->RenderMode==GL_RENDER) {
+ if (bitmap) {
+ /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
+ GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
+ GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ ctx->OcclusionResult = GL_TRUE;
+ ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
+ }
+ }
+#if _HAVE_FULL_GL
+ else if (ctx->RenderMode==GL_FEEDBACK) {
+ if (ctx->Current.RasterPosValid) {
+ FLUSH_CURRENT(ctx, 0);
+ FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterIndex,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ /* Bitmaps don't generate selection hits. See appendix B of 1.1 spec. */
+ }
+#endif
+
+ /* update raster position */
+ ctx->Current.RasterPos[0] += xmove;
+ ctx->Current.RasterPos[1] += ymove;
+}
+
+
+
+#if 0 /* experimental */
+/*
+ * Execute glDrawDepthPixelsMESA(). This function accepts both a color
+ * image and depth (Z) image. Rasterization produces fragments with
+ * color and Z taken from these images. This function is intended for
+ * Z-compositing. Normally, this operation requires two glDrawPixels
+ * calls with stencil testing.
+ */
+void GLAPIENTRY
+_mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height,
+ GLenum colorFormat, GLenum colorType,
+ const GLvoid *colors,
+ GLenum depthType, const GLvoid *depths )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);