+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portionsalloc
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "enums.h"
-#include "state.h"
-#include "swrast/swrast.h"
-
-#include "intel_context.h"
-#include "intel_pixel.h"
-#include "intel_regions.h"
-
-
-/**
- * Check if any fragment operations are in effect which might effect
- * glDraw/CopyPixels.
- */
-GLboolean
-intel_check_blit_fragment_ops(GLcontext * ctx)
-{
- if (ctx->NewState)
- _mesa_update_state(ctx);
-
- /* XXX Note: Scissor could be done with the blitter:
- */
- return !(ctx->_ImageTransferState ||
- ctx->Color.AlphaEnabled ||
- ctx->Depth.Test ||
- ctx->Fog.Enabled ||
- ctx->Scissor.Enabled ||
- ctx->Stencil.Enabled ||
- !ctx->Color.ColorMask[0] ||
- !ctx->Color.ColorMask[1] ||
- !ctx->Color.ColorMask[2] ||
- !ctx->Color.ColorMask[3] ||
- ctx->Texture._EnabledUnits ||
- ctx->FragmentProgram._Enabled ||
- ctx->Color.BlendEnabled);
-}
-
-
-GLboolean
-intel_check_meta_tex_fragment_ops(GLcontext * ctx)
-{
- if (ctx->NewState)
- _mesa_update_state(ctx);
-
- /* Some of _ImageTransferState (scale, bias) could be done with
- * fragment programs on i915.
- */
- return !(ctx->_ImageTransferState || ctx->Fog.Enabled || /* not done yet */
- ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled);
-}
-
-/* The intel_region struct doesn't really do enough to capture the
- * format of the pixels in the region. For now this code assumes that
- * the region is a display surface and hence is either ARGB8888 or
- * RGB565.
- * XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd
- * know the buffer's pixel format.
- *
- * \param format as given to glDraw/ReadPixels
- * \param type as given to glDraw/ReadPixels
- */
-GLboolean
-intel_check_blit_format(struct intel_region * region,
- GLenum format, GLenum type)
-{
- if (region->cpp == 4 &&
- (type == GL_UNSIGNED_INT_8_8_8_8_REV ||
- type == GL_UNSIGNED_BYTE) && format == GL_BGRA) {
- return GL_TRUE;
- }
-
- if (region->cpp == 2 &&
- type == GL_UNSIGNED_SHORT_5_6_5_REV && format == GL_BGR) {
- return GL_TRUE;
- }
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",
- __FUNCTION__, region->cpp,
- _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
-
- return GL_FALSE;
-}
-
-
-void
-intelInitPixelFuncs(struct dd_function_table *functions)
-{
- functions->Accum = _swrast_Accum;
- functions->Bitmap = _swrast_Bitmap;
- functions->CopyPixels = intelCopyPixels;
- functions->ReadPixels = intelReadPixels;
- functions->DrawPixels = intelDrawPixels;
-}
--- /dev/null
+../intel/intel_pixel.c
\ No newline at end of file
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef INTEL_PIXEL_H
-#define INTEL_PIXEL_H
-
-#include "mtypes.h"
-
-void intelInitPixelFuncs(struct dd_function_table *functions);
-
-GLboolean intel_check_blit_fragment_ops(GLcontext * ctx);
-
-GLboolean intel_check_meta_tex_fragment_ops(GLcontext * ctx);
-
-GLboolean intel_check_blit_format(struct intel_region *region,
- GLenum format, GLenum type);
-
-
-void intelReadPixels(GLcontext * ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *pack,
- GLvoid * pixels);
-
-void intelDrawPixels(GLcontext * ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum format,
- GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid * pixels);
-
-void intelCopyPixels(GLcontext * ctx,
- GLint srcx, GLint srcy,
- GLsizei width, GLsizei height,
- GLint destx, GLint desty, GLenum type);
-
-#endif
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "glheader.h"
-#include "enums.h"
-#include "image.h"
-#include "state.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "swrast/swrast.h"
-
-#include "intel_screen.h"
-#include "intel_context.h"
-#include "intel_ioctl.h"
-#include "intel_batchbuffer.h"
-#include "intel_buffers.h"
-#include "intel_blit.h"
-#include "intel_regions.h"
-#include "intel_tris.h"
-#include "intel_pixel.h"
-
-#define FILE_DEBUG_FLAG DEBUG_PIXEL
-
-static struct intel_region *
-copypix_src_region(struct intel_context *intel, GLenum type)
-{
- switch (type) {
- case GL_COLOR:
- return intel_readbuf_region(intel);
- case GL_DEPTH:
- /* Don't think this is really possible execpt at 16bpp, when we have no stencil.
- */
- if (intel->depth_region && intel->depth_region->cpp == 2)
- return intel->depth_region;
- case GL_STENCIL:
- /* Don't think this is really possible.
- */
- break;
- case GL_DEPTH_STENCIL_EXT:
- /* Does it matter whether it is stencil/depth or depth/stencil?
- */
- return intel->depth_region;
- default:
- break;
- }
-
- return NULL;
-}
-
-
-/**
- * Check if any fragment operations are in effect which might effect
- * glCopyPixels. Differs from intel_check_blit_fragment_ops in that
- * we allow Scissor.
- */
-static GLboolean
-intel_check_copypixel_blit_fragment_ops(GLcontext * ctx)
-{
- if (ctx->NewState)
- _mesa_update_state(ctx);
-
- /* Could do logicop with the blitter:
- */
- return !(ctx->_ImageTransferState ||
- ctx->Color.AlphaEnabled ||
- ctx->Depth.Test ||
- ctx->Fog.Enabled ||
- ctx->Stencil.Enabled ||
- !ctx->Color.ColorMask[0] ||
- !ctx->Color.ColorMask[1] ||
- !ctx->Color.ColorMask[2] ||
- !ctx->Color.ColorMask[3] ||
- ctx->Texture._EnabledUnits ||
- ctx->FragmentProgram._Enabled ||
- ctx->Color.BlendEnabled);
-}
-
-/* Doesn't work for overlapping regions. Could do a double copy or
- * just fallback.
- */
-static GLboolean
-do_texture_copypixels(GLcontext * ctx,
- GLint srcx, GLint srcy,
- GLsizei width, GLsizei height,
- GLint dstx, GLint dsty, GLenum type)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_region *dst = intel_drawbuf_region(intel);
- struct intel_region *src = copypix_src_region(intel, type);
- GLenum src_format;
- GLenum src_type;
-
- DBG("%s %d,%d %dx%d --> %d,%d\n", __FUNCTION__,
- srcx, srcy, width, height, dstx, dsty);
-
- if (!src || !dst || type != GL_COLOR)
- return GL_FALSE;
-
- /* Can't handle overlapping regions. Don't have sufficient control
- * over rasterization to pull it off in-place. Punt on these for
- * now.
- *
- * XXX: do a copy to a temporary.
- */
- if (src->buffer == dst->buffer) {
- drm_clip_rect_t srcbox;
- drm_clip_rect_t dstbox;
- drm_clip_rect_t tmp;
-
- srcbox.x1 = srcx;
- srcbox.y1 = srcy;
- srcbox.x2 = srcx + width;
- srcbox.y2 = srcy + height;
-
- dstbox.x1 = dstx;
- dstbox.y1 = dsty;
- dstbox.x2 = dstx + width * ctx->Pixel.ZoomX;
- dstbox.y2 = dsty + height * ctx->Pixel.ZoomY;
-
- DBG("src %d,%d %d,%d\n", srcbox.x1, srcbox.y1, srcbox.x2, srcbox.y2);
- DBG("dst %d,%d %d,%d (%dx%d) (%f,%f)\n", dstbox.x1, dstbox.y1, dstbox.x2, dstbox.y2,
- width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
-
- if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) {
- DBG("%s: regions overlap\n", __FUNCTION__);
- return GL_FALSE;
- }
- }
-
- intelFlush(&intel->ctx);
-
- intel->vtbl.install_meta_state(intel);
-
- /* Is this true? Also will need to turn depth testing on according
- * to state:
- */
- intel->vtbl.meta_no_stencil_write(intel);
- intel->vtbl.meta_no_depth_write(intel);
-
- /* Set the 3d engine to draw into the destination region:
- */
- intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
-
- intel->vtbl.meta_import_pixel_state(intel);
-
- if (src->cpp == 2) {
- src_format = GL_RGB;
- src_type = GL_UNSIGNED_SHORT_5_6_5;
- }
- else {
- src_format = GL_BGRA;
- src_type = GL_UNSIGNED_BYTE;
- }
-
- /* Set the frontbuffer up as a large rectangular texture.
- */
- if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, 0,
- src->pitch,
- src->height, src_format, src_type)) {
- intel->vtbl.leave_meta_state(intel);
- return GL_FALSE;
- }
-
-
- intel->vtbl.meta_texture_blend_replace(intel);
-
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
-
-
- srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
-
- srcx += dPriv->x;
- srcy += dPriv->y;
-
- /* Clip against the source region. This is the only source
- * clipping we do. XXX: Just set the texcord wrap mode to clamp
- * or similar.
- *
- */
- if (0) {
- GLint orig_x = srcx;
- GLint orig_y = srcy;
-
- if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
- &srcx, &srcy, &width, &height))
- goto out;
-
- dstx += srcx - orig_x;
- dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;
- }
-
- /* Just use the regular cliprect mechanism... Does this need to
- * even hold the lock???
- */
- intel->vtbl.meta_draw_quad(intel,
- dstx,
- dstx + width * ctx->Pixel.ZoomX,
- dPriv->h - (dsty + height * ctx->Pixel.ZoomY),
- dPriv->h - (dsty), 0, /* XXX: what z value? */
- 0x00ff00ff,
- srcx, srcx + width, srcy, srcy + height);
-
- out:
- intel->vtbl.leave_meta_state(intel);
- intel_batchbuffer_flush(intel->batch);
- }
- UNLOCK_HARDWARE(intel);
-
- DBG("%s: success\n", __FUNCTION__);
- return GL_TRUE;
-}
-
-
-
-
-
-/**
- * CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
- */
-static GLboolean
-do_blit_copypixels(GLcontext * ctx,
- GLint srcx, GLint srcy,
- GLsizei width, GLsizei height,
- GLint dstx, GLint dsty, GLenum type)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_region *dst = intel_drawbuf_region(intel);
- struct intel_region *src = copypix_src_region(intel, type);
-
- /* Copypixels can be more than a straight copy. Ensure all the
- * extra operations are disabled:
- */
- if (!intel_check_copypixel_blit_fragment_ops(ctx) ||
- ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
- return GL_FALSE;
-
- if (!src || !dst)
- return GL_FALSE;
-
-
-
- intelFlush(&intel->ctx);
-
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t dest_rect;
- GLint nbox = dPriv->numClipRects;
- GLint delta_x = 0;
- GLint delta_y = 0;
- GLuint i;
-
- /* Do scissoring in GL coordinates:
- */
- if (ctx->Scissor.Enabled)
- {
- GLint x = ctx->Scissor.X;
- GLint y = ctx->Scissor.Y;
- GLuint w = ctx->Scissor.Width;
- GLuint h = ctx->Scissor.Height;
- GLint dx = dstx - srcx;
- GLint dy = dsty - srcy;
-
- if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height))
- goto out;
-
- srcx = dstx - dx;
- srcy = dsty - dy;
- }
-
- /* Convert from GL to hardware coordinates:
- */
- dsty = dPriv->h - dsty - height;
- srcy = dPriv->h - srcy - height;
- dstx += dPriv->x;
- dsty += dPriv->y;
- srcx += dPriv->x;
- srcy += dPriv->y;
-
- /* Clip against the source region. This is the only source
- * clipping we do. Dst is clipped with cliprects below.
- */
- {
- delta_x = srcx - dstx;
- delta_y = srcy - dsty;
-
- if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
- &srcx, &srcy, &width, &height))
- goto out;
-
- dstx = srcx - delta_x;
- dsty = srcy - delta_y;
- }
-
- dest_rect.x1 = dstx;
- dest_rect.y1 = dsty;
- dest_rect.x2 = dstx + width;
- dest_rect.y2 = dsty + height;
-
- /* Could do slightly more clipping: Eg, take the intersection of
- * the existing set of cliprects and those cliprects translated
- * by delta_x, delta_y:
- *
- * This code will not overwrite other windows, but will
- * introduce garbage when copying from obscured window regions.
- */
- for (i = 0; i < nbox; i++) {
- drm_clip_rect_t rect;
-
- if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
- continue;
-
-
- intelEmitCopyBlit(intel, dst->cpp,
- src->pitch, src->buffer, 0, src->tiled,
- dst->pitch, dst->buffer, 0, dst->tiled,
- rect.x1 + delta_x,
- rect.y1 + delta_y, /* srcx, srcy */
- rect.x1, rect.y1, /* dstx, dsty */
- rect.x2 - rect.x1, rect.y2 - rect.y1,
- ctx->Color.ColorLogicOpEnabled ?
- ctx->Color.LogicOp : GL_COPY);
- }
-
- out:
- intel_batchbuffer_flush(intel->batch);
- }
- UNLOCK_HARDWARE(intel);
-
- DBG("%s: success\n", __FUNCTION__);
- return GL_TRUE;
-}
-
-
-void
-intelCopyPixels(GLcontext * ctx,
- GLint srcx, GLint srcy,
- GLsizei width, GLsizei height,
- GLint destx, GLint desty, GLenum type)
-{
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
- return;
-
- if (do_texture_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
- return;
-
- DBG("fallback to _swrast_CopyPixels\n");
-
- _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type);
-}
--- /dev/null
+../intel/intel_pixel_copy.c
\ No newline at end of file
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portionsalloc
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "glheader.h"
-#include "enums.h"
-#include "image.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "bufferobj.h"
-#include "swrast/swrast.h"
-
-#include "intel_screen.h"
-#include "intel_context.h"
-#include "intel_ioctl.h"
-#include "intel_batchbuffer.h"
-#include "intel_blit.h"
-#include "intel_buffers.h"
-#include "intel_regions.h"
-#include "intel_pixel.h"
-#include "intel_buffer_objects.h"
-#include "intel_tris.h"
-
-
-
-static GLboolean
-do_texture_drawpixels(GLcontext * ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid * pixels)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_region *dst = intel_drawbuf_region(intel);
- struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
- GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
- GLuint src_offset;
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- intelFlush(&intel->ctx);
- intel->vtbl.render_start(intel);
- intel->vtbl.emit_state(intel);
-
- if (!dst)
- return GL_FALSE;
-
- if (src) {
- if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
- return GL_TRUE;
- }
- }
- else {
- /* PBO only for now:
- */
-/* _mesa_printf("%s - not PBO\n", __FUNCTION__); */
- return GL_FALSE;
- }
-
- /* There are a couple of things we can't do yet, one of which is
- * set the correct state for pixel operations when GL texturing is
- * enabled. That's a pretty rare state and probably not worth the
- * effort. A completely device-independent version of this may do
- * more.
- *
- * Similarly, we make no attempt to merge metaops processing with
- * an enabled fragment program, though it would certainly be
- * possible.
- */
- if (!intel_check_meta_tex_fragment_ops(ctx)) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - bad GL fragment state for metaops texture\n",
- __FUNCTION__);
- return GL_FALSE;
- }
-
- intel->vtbl.install_meta_state(intel);
-
-
- /* Is this true? Also will need to turn depth testing on according
- * to state:
- */
- intel->vtbl.meta_no_stencil_write(intel);
- intel->vtbl.meta_no_depth_write(intel);
-
- /* Set the 3d engine to draw into the destination region:
- */
- intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
-
- intel->vtbl.meta_import_pixel_state(intel);
-
- src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
- format, type, 0, 0, 0);
-
-
- /* Setup the pbo up as a rectangular texture, if possible.
- *
- * TODO: This is almost always possible if the i915 fragment
- * program is adjusted to correctly swizzle the sampled colors.
- * The major exception is any 24bit texture, like RGB888, for which
- * there is no hardware support.
- */
- if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, src_offset,
- rowLength, height, format, type)) {
- intel->vtbl.leave_meta_state(intel);
- return GL_FALSE;
- }
-
- intel->vtbl.meta_texture_blend_replace(intel);
-
-
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- GLint srcx, srcy;
- GLint dstx, dsty;
-
- dstx = x;
- dsty = dPriv->h - (y + height);
-
- srcx = 0; /* skiprows/pixels already done */
- srcy = 0;
-
- if (0) {
- const GLint orig_x = dstx;
- const GLint orig_y = dsty;
-
- if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
- &dstx, &dsty, &width, &height))
- goto out;
-
- srcx += dstx - orig_x;
- srcy += dsty - orig_y;
- }
-
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("draw %d,%d %dx%d\n", dstx, dsty, width, height);
-
- /* Must use the regular cliprect mechanism in order to get the
- * drawing origin set correctly. Otherwise scissor state is in
- * incorrect coordinate space. Does this even need to hold the
- * lock???
- */
- intel->vtbl.meta_draw_quad(intel,
- dstx, dstx + width * ctx->Pixel.ZoomX,
- dPriv->h - (y + height * ctx->Pixel.ZoomY),
- dPriv->h - (y),
- -ctx->Current.RasterPos[2] * .5,
- 0x00ff00ff,
- srcx, srcx + width, srcy + height, srcy);
- out:
- intel->vtbl.leave_meta_state(intel);
- intel_batchbuffer_flush(intel->batch);
- }
- UNLOCK_HARDWARE(intel);
- return GL_TRUE;
-}
-
-
-
-
-
-/* Pros:
- * - no waiting for idle before updating framebuffer.
- *
- * Cons:
- * - if upload is by memcpy, this may actually be slower than fallback path.
- * - uploads the whole image even if destination is clipped
- *
- * Need to benchmark.
- *
- * Given the questions about performance, implement for pbo's only.
- * This path is definitely a win if the pbo is already in agp. If it
- * turns out otherwise, we can add the code necessary to upload client
- * data to agp space before performing the blit. (Though it may turn
- * out to be better/simpler just to use the texture engine).
- */
-static GLboolean
-do_blit_drawpixels(GLcontext * ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid * pixels)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_region *dest = intel_drawbuf_region(intel);
- struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
- GLuint src_offset;
- GLuint rowLength;
- dri_fence *fence = NULL;
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s\n", __FUNCTION__);
-
-
- if (!dest) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - no dest\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- if (src) {
- /* This validation should be done by core mesa:
- */
- if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
- return GL_TRUE;
- }
- }
- else {
- /* PBO only for now:
- */
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - not PBO\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- if (!intel_check_blit_format(dest, format, type)) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- if (!intel_check_blit_fragment_ops(ctx)) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - bad GL fragment state for blitter\n",
- __FUNCTION__);
- return GL_FALSE;
- }
-
- if (ctx->Pixel.ZoomX != 1.0F) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
- return GL_FALSE;
- }
-
-
- if (unpack->RowLength > 0)
- rowLength = unpack->RowLength;
- else
- rowLength = width;
-
- if (ctx->Pixel.ZoomY == -1.0F) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
- return GL_FALSE; /* later */
- y -= height;
- }
- else if (ctx->Pixel.ZoomY == 1.0F) {
- rowLength = -rowLength;
- }
- else {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
- format, type, 0, 0, 0);
-
- intelFlush(&intel->ctx);
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- int nbox = dPriv->numClipRects;
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t rect;
- drm_clip_rect_t dest_rect;
- dri_bo *src_buffer = intel_bufferobj_buffer(intel, src, INTEL_READ);
- int i;
-
- dest_rect.x1 = dPriv->x + x;
- dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
- dest_rect.x2 = dest_rect.x1 + width;
- dest_rect.y2 = dest_rect.y1 + height;
-
- for (i = 0; i < nbox; i++) {
- if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
- continue;
-
- intelEmitCopyBlit(intel,
- dest->cpp,
- rowLength, src_buffer, src_offset, GL_FALSE,
- dest->pitch, dest->buffer, 0, dest->tiled,
- rect.x1 - dest_rect.x1,
- rect.y2 - dest_rect.y2,
- rect.x1,
- rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1,
- ctx->Color.ColorLogicOpEnabled ?
- ctx->Color.LogicOp : GL_COPY);
- }
- intel_batchbuffer_flush(intel->batch);
- fence = intel->batch->last_fence;
- dri_fence_reference(fence);
- }
- UNLOCK_HARDWARE(intel);
-
- if (fence) {
- dri_fence_wait(fence);
- dri_fence_unreference(fence);
- }
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - DONE\n", __FUNCTION__);
-
- return GL_TRUE;
-}
-
-
-
-void
-intelDrawPixels(GLcontext * ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum format,
- GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid * pixels)
-{
- if (do_blit_drawpixels(ctx, x, y, width, height, format, type,
- unpack, pixels))
- return;
-
- if (do_texture_drawpixels(ctx, x, y, width, height, format, type,
- unpack, pixels))
- return;
-
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
-
- if (ctx->FragmentProgram._Current == ctx->FragmentProgram._TexEnvProgram) {
- /*
- * We don't want the i915 texenv program to be applied to DrawPixels.
- * This is really just a performance optimization (mesa will other-
- * wise happily run the fragment program on each pixel in the image).
- */
- struct gl_fragment_program *fpSave = ctx->FragmentProgram._Current;
- /* can't just set current frag prog to 0 here as on buffer resize
- we'll get new state checks which will segfault. Remains a hack. */
- ctx->FragmentProgram._Current = NULL;
- ctx->FragmentProgram._UseTexEnvProgram = GL_FALSE;
- ctx->FragmentProgram._Active = GL_FALSE;
- _swrast_DrawPixels( ctx, x, y, width, height, format, type,
- unpack, pixels );
- ctx->FragmentProgram._Current = fpSave;
- ctx->FragmentProgram._UseTexEnvProgram = GL_TRUE;
- ctx->FragmentProgram._Active = GL_TRUE;
- }
- else {
- _swrast_DrawPixels( ctx, x, y, width, height, format, type,
- unpack, pixels );
- }
-}
--- /dev/null
+../intel/intel_pixel_draw.c
\ No newline at end of file
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portionsalloc
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "glheader.h"
-#include "enums.h"
-#include "image.h"
-#include "colormac.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "bufferobj.h"
-#include "swrast/swrast.h"
-
-#include "intel_screen.h"
-#include "intel_context.h"
-#include "intel_ioctl.h"
-#include "intel_batchbuffer.h"
-#include "intel_blit.h"
-#include "intel_regions.h"
-#include "intel_buffer_objects.h"
-
-
-
-#define FILE_DEBUG_FLAG DEBUG_PIXEL
-
-
-/* Unlike the other intel_pixel_* functions, the expectation here is
- * that the incoming data is not in a PBO. With the XY_TEXT blit
- * method, there's no benefit haveing it in a PBO, but we could
- * implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
- * PBO bitmaps. I think they are probably pretty rare though - I
- * wonder if Xgl uses them?
- */
-static const GLubyte *map_pbo( GLcontext *ctx,
- GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap )
-{
- GLubyte *buf;
-
- if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
- GL_COLOR_INDEX, GL_BITMAP,
- (GLvoid *) bitmap)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
- return NULL;
- }
-
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- unpack->BufferObj);
- if (!buf) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
- return NULL;
- }
-
- return ADD_POINTERS(buf, bitmap);
-}
-
-static GLboolean test_bit( const GLubyte *src,
- GLuint bit )
-{
- return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0;
-}
-
-static void set_bit( GLubyte *dest,
- GLuint bit )
-{
- dest[bit/8] |= 1 << (bit % 8);
-}
-
-/* Extract a rectangle's worth of data from the bitmap. Called
- * per-cliprect.
- */
-static GLuint get_bitmap_rect(GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap,
- GLuint x, GLuint y,
- GLuint w, GLuint h,
- GLubyte *dest,
- GLuint row_align,
- GLboolean invert)
-{
- GLuint src_offset = (x + unpack->SkipPixels) & 0x7;
- GLuint mask = unpack->LsbFirst ? 0 : 7;
- GLuint bit = 0;
- GLint row, col;
- GLint first, last;
- GLint incr;
- GLuint count = 0;
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n",
- __FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask);
-
- if (invert) {
- first = h-1;
- last = 0;
- incr = -1;
- }
- else {
- first = 0;
- last = h-1;
- incr = 1;
- }
-
- /* Require that dest be pre-zero'd.
- */
- for (row = first; row != (last+incr); row += incr) {
- const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap,
- width, height,
- GL_COLOR_INDEX, GL_BITMAP,
- y + row, x);
-
- for (col = 0; col < w; col++, bit++) {
- if (test_bit(rowsrc, (col + src_offset) ^ mask)) {
- set_bit(dest, bit ^ 7);
- count++;
- }
- }
-
- if (row_align)
- bit = ALIGN(bit, row_align);
- }
-
- return count;
-}
-
-
-
-
-/*
- * Render a bitmap.
- */
-static GLboolean
-do_blit_bitmap( GLcontext *ctx,
- GLint dstx, GLint dsty,
- GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap )
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_region *dst = intel_drawbuf_region(intel);
- GLfloat tmpColor[4];
-
- union {
- GLuint ui;
- GLubyte ub[4];
- } color;
-
- if (!dst)
- return GL_FALSE;
-
- if (unpack->BufferObj->Name) {
- bitmap = map_pbo(ctx, width, height, unpack, bitmap);
- if (bitmap == NULL)
- return GL_TRUE; /* even though this is an error, we're done */
- }
-
- COPY_4V(tmpColor, ctx->Current.RasterColor);
-
- if (NEED_SECONDARY_COLOR(ctx)) {
- ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
- }
-
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[0], tmpColor[2]);
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[1], tmpColor[1]);
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[2], tmpColor[0]);
- UNCLAMPED_FLOAT_TO_CHAN(color.ub[3], tmpColor[3]);
-
- /* Does zoom apply to bitmaps?
- */
- if (!intel_check_blit_fragment_ops(ctx) ||
- ctx->Pixel.ZoomX != 1.0F ||
- ctx->Pixel.ZoomY != 1.0F)
- return GL_FALSE;
-
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t dest_rect;
- GLint nbox = dPriv->numClipRects;
- GLint srcx = 0, srcy = 0;
- GLint orig_screen_x1, orig_screen_y2;
- GLuint i;
-
-
- orig_screen_x1 = dPriv->x + dstx;
- orig_screen_y2 = dPriv->y + (dPriv->h - dsty);
-
- /* Do scissoring in GL coordinates:
- */
- if (ctx->Scissor.Enabled)
- {
- GLint x = ctx->Scissor.X;
- GLint y = ctx->Scissor.Y;
- GLuint w = ctx->Scissor.Width;
- GLuint h = ctx->Scissor.Height;
-
- if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height))
- goto out;
- }
-
- /* Convert from GL to hardware coordinates:
- */
- dsty = dPriv->y + (dPriv->h - dsty - height);
- dstx = dPriv->x + dstx;
-
- dest_rect.x1 = dstx < 0 ? 0 : dstx;
- dest_rect.y1 = dsty < 0 ? 0 : dsty;
- dest_rect.x2 = dstx + width < 0 ? 0 : dstx + width;
- dest_rect.y2 = dsty + height < 0 ? 0 : dsty + height;
-
- for (i = 0; i < nbox; i++) {
- drm_clip_rect_t rect;
- int box_w, box_h;
- GLint px, py;
- GLuint stipple[32];
-
- if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
- continue;
-
- /* Now go back to GL coordinates to figure out what subset of
- * the bitmap we are uploading for this cliprect:
- */
- box_w = rect.x2 - rect.x1;
- box_h = rect.y2 - rect.y1;
- srcx = rect.x1 - orig_screen_x1;
- srcy = orig_screen_y2 - rect.y2;
-
-
-#define DY 32
-#define DX 32
-
- /* Then, finally, chop it all into chunks that can be
- * digested by hardware:
- */
- for (py = 0; py < box_h; py += DY) {
- for (px = 0; px < box_w; px += DX) {
- int h = MIN2(DY, box_h - py);
- int w = MIN2(DX, box_w - px);
- GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8;
- GLenum logic_op = ctx->Color.ColorLogicOpEnabled ?
- ctx->Color.LogicOp : GL_COPY;
-
- assert(sz <= sizeof(stipple));
- memset(stipple, 0, sz);
-
- /* May need to adjust this when padding has been introduced in
- * sz above:
- */
- if (get_bitmap_rect(width, height, unpack,
- bitmap,
- srcx + px, srcy + py, w, h,
- (GLubyte *)stipple,
- 8,
- GL_TRUE) == 0)
- continue;
-
- /*
- */
- intelEmitImmediateColorExpandBlit( intel,
- dst->cpp,
- (GLubyte *)stipple,
- sz,
- color.ui,
- dst->pitch,
- dst->buffer,
- 0,
- dst->tiled,
- rect.x1 + px,
- rect.y2 - (py + h),
- w, h,
- logic_op);
- }
- }
- }
- intel->need_flush = GL_TRUE;
- out:
- intel_batchbuffer_flush(intel->batch);
- }
- UNLOCK_HARDWARE(intel);
-
-
- if (unpack->BufferObj->Name) {
- /* done with PBO so unmap it now */
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- unpack->BufferObj);
- }
-
- return GL_TRUE;
-}
-
-
-
-
-
-/* There are a large number of possible ways to implement bitmap on
- * this hardware, most of them have some sort of drawback. Here are a
- * few that spring to mind:
- *
- * Blit:
- * - XY_MONO_SRC_BLT_CMD
- * - use XY_SETUP_CLIP_BLT for cliprect clipping.
- * - XY_TEXT_BLT
- * - XY_TEXT_IMMEDIATE_BLT
- * - blit per cliprect, subject to maximum immediate data size.
- * - XY_COLOR_BLT
- * - per pixel or run of pixels
- * - XY_PIXEL_BLT
- * - good for sparse bitmaps
- *
- * 3D engine:
- * - Point per pixel
- * - Translate bitmap to an alpha texture and render as a quad
- * - Chop bitmap up into 32x32 squares and render w/polygon stipple.
- */
-void
-intelBitmap(GLcontext * ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte * pixels)
-{
- if (do_blit_bitmap(ctx, x, y, width, height,
- unpack, pixels))
- return;
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
-
- _swrast_Bitmap(ctx, x, y, width, height, unpack, pixels);
-}
--- /dev/null
+../intel/intel_pixel_bitmap.c
\ No newline at end of file
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portionsalloc
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "enums.h"
+#include "state.h"
+#include "swrast/swrast.h"
+
+#include "intel_context.h"
+#include "intel_pixel.h"
+#include "intel_regions.h"
+
+
+/**
+ * Check if any fragment operations are in effect which might effect
+ * glDraw/CopyPixels.
+ */
+GLboolean
+intel_check_blit_fragment_ops(GLcontext * ctx)
+{
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ /* XXX Note: Scissor could be done with the blitter:
+ */
+ return !(ctx->_ImageTransferState ||
+ ctx->Color.AlphaEnabled ||
+ ctx->Depth.Test ||
+ ctx->Fog.Enabled ||
+ ctx->Scissor.Enabled ||
+ ctx->Stencil.Enabled ||
+ !ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3] ||
+ ctx->Texture._EnabledUnits ||
+ ctx->FragmentProgram._Enabled ||
+ ctx->Color.BlendEnabled);
+}
+
+
+GLboolean
+intel_check_meta_tex_fragment_ops(GLcontext * ctx)
+{
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ /* Some of _ImageTransferState (scale, bias) could be done with
+ * fragment programs on i915.
+ */
+ return !(ctx->_ImageTransferState || ctx->Fog.Enabled || /* not done yet */
+ ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled);
+}
+
+/* The intel_region struct doesn't really do enough to capture the
+ * format of the pixels in the region. For now this code assumes that
+ * the region is a display surface and hence is either ARGB8888 or
+ * RGB565.
+ * XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd
+ * know the buffer's pixel format.
+ *
+ * \param format as given to glDraw/ReadPixels
+ * \param type as given to glDraw/ReadPixels
+ */
+GLboolean
+intel_check_blit_format(struct intel_region * region,
+ GLenum format, GLenum type)
+{
+ if (region->cpp == 4 &&
+ (type == GL_UNSIGNED_INT_8_8_8_8_REV ||
+ type == GL_UNSIGNED_BYTE) && format == GL_BGRA) {
+ return GL_TRUE;
+ }
+
+ if (region->cpp == 2 &&
+ type == GL_UNSIGNED_SHORT_5_6_5_REV && format == GL_BGR) {
+ return GL_TRUE;
+ }
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",
+ __FUNCTION__, region->cpp,
+ _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
+
+ return GL_FALSE;
+}
+
+
+void
+intelInitPixelFuncs(struct dd_function_table *functions)
+{
+ functions->Accum = _swrast_Accum;
+ functions->Bitmap = _swrast_Bitmap;
+ functions->CopyPixels = intelCopyPixels;
+ functions->ReadPixels = intelReadPixels;
+ functions->DrawPixels = intelDrawPixels;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef INTEL_PIXEL_H
+#define INTEL_PIXEL_H
+
+#include "mtypes.h"
+
+void intelInitPixelFuncs(struct dd_function_table *functions);
+
+GLboolean intel_check_blit_fragment_ops(GLcontext * ctx);
+
+GLboolean intel_check_meta_tex_fragment_ops(GLcontext * ctx);
+
+GLboolean intel_check_blit_format(struct intel_region *region,
+ GLenum format, GLenum type);
+
+
+void intelReadPixels(GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid * pixels);
+
+void intelDrawPixels(GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format,
+ GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels);
+
+void intelCopyPixels(GLcontext * ctx,
+ GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint destx, GLint desty, GLenum type);
+
+#endif
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portionsalloc
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "image.h"
+#include "colormac.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "bufferobj.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_regions.h"
+#include "intel_buffer_objects.h"
+
+
+
+#define FILE_DEBUG_FLAG DEBUG_PIXEL
+
+
+/* Unlike the other intel_pixel_* functions, the expectation here is
+ * that the incoming data is not in a PBO. With the XY_TEXT blit
+ * method, there's no benefit haveing it in a PBO, but we could
+ * implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
+ * PBO bitmaps. I think they are probably pretty rare though - I
+ * wonder if Xgl uses them?
+ */
+static const GLubyte *map_pbo( GLcontext *ctx,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ GLubyte *buf;
+
+ if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+ GL_COLOR_INDEX, GL_BITMAP,
+ (GLvoid *) bitmap)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
+ return NULL;
+ }
+
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB,
+ unpack->BufferObj);
+ if (!buf) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
+ return NULL;
+ }
+
+ return ADD_POINTERS(buf, bitmap);
+}
+
+static GLboolean test_bit( const GLubyte *src,
+ GLuint bit )
+{
+ return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0;
+}
+
+static void set_bit( GLubyte *dest,
+ GLuint bit )
+{
+ dest[bit/8] |= 1 << (bit % 8);
+}
+
+/* Extract a rectangle's worth of data from the bitmap. Called
+ * per-cliprect.
+ */
+static GLuint get_bitmap_rect(GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ GLuint x, GLuint y,
+ GLuint w, GLuint h,
+ GLubyte *dest,
+ GLuint row_align,
+ GLboolean invert)
+{
+ GLuint src_offset = (x + unpack->SkipPixels) & 0x7;
+ GLuint mask = unpack->LsbFirst ? 0 : 7;
+ GLuint bit = 0;
+ GLint row, col;
+ GLint first, last;
+ GLint incr;
+ GLuint count = 0;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n",
+ __FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask);
+
+ if (invert) {
+ first = h-1;
+ last = 0;
+ incr = -1;
+ }
+ else {
+ first = 0;
+ last = h-1;
+ incr = 1;
+ }
+
+ /* Require that dest be pre-zero'd.
+ */
+ for (row = first; row != (last+incr); row += incr) {
+ const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap,
+ width, height,
+ GL_COLOR_INDEX, GL_BITMAP,
+ y + row, x);
+
+ for (col = 0; col < w; col++, bit++) {
+ if (test_bit(rowsrc, (col + src_offset) ^ mask)) {
+ set_bit(dest, bit ^ 7);
+ count++;
+ }
+ }
+
+ if (row_align)
+ bit = ALIGN(bit, row_align);
+ }
+
+ return count;
+}
+
+
+
+
+/*
+ * Render a bitmap.
+ */
+static GLboolean
+do_blit_bitmap( GLcontext *ctx,
+ GLint dstx, GLint dsty,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_region *dst = intel_drawbuf_region(intel);
+ GLfloat tmpColor[4];
+
+ union {
+ GLuint ui;
+ GLubyte ub[4];
+ } color;
+
+ if (!dst)
+ return GL_FALSE;
+
+ if (unpack->BufferObj->Name) {
+ bitmap = map_pbo(ctx, width, height, unpack, bitmap);
+ if (bitmap == NULL)
+ return GL_TRUE; /* even though this is an error, we're done */
+ }
+
+ COPY_4V(tmpColor, ctx->Current.RasterColor);
+
+ if (NEED_SECONDARY_COLOR(ctx)) {
+ ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
+ }
+
+ UNCLAMPED_FLOAT_TO_CHAN(color.ub[0], tmpColor[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(color.ub[1], tmpColor[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(color.ub[2], tmpColor[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(color.ub[3], tmpColor[3]);
+
+ /* Does zoom apply to bitmaps?
+ */
+ if (!intel_check_blit_fragment_ops(ctx) ||
+ ctx->Pixel.ZoomX != 1.0F ||
+ ctx->Pixel.ZoomY != 1.0F)
+ return GL_FALSE;
+
+ LOCK_HARDWARE(intel);
+
+ if (intel->driDrawable->numClipRects) {
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t dest_rect;
+ GLint nbox = dPriv->numClipRects;
+ GLint srcx = 0, srcy = 0;
+ GLint orig_screen_x1, orig_screen_y2;
+ GLuint i;
+
+
+ orig_screen_x1 = dPriv->x + dstx;
+ orig_screen_y2 = dPriv->y + (dPriv->h - dsty);
+
+ /* Do scissoring in GL coordinates:
+ */
+ if (ctx->Scissor.Enabled)
+ {
+ GLint x = ctx->Scissor.X;
+ GLint y = ctx->Scissor.Y;
+ GLuint w = ctx->Scissor.Width;
+ GLuint h = ctx->Scissor.Height;
+
+ if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height))
+ goto out;
+ }
+
+ /* Convert from GL to hardware coordinates:
+ */
+ dsty = dPriv->y + (dPriv->h - dsty - height);
+ dstx = dPriv->x + dstx;
+
+ dest_rect.x1 = dstx < 0 ? 0 : dstx;
+ dest_rect.y1 = dsty < 0 ? 0 : dsty;
+ dest_rect.x2 = dstx + width < 0 ? 0 : dstx + width;
+ dest_rect.y2 = dsty + height < 0 ? 0 : dsty + height;
+
+ for (i = 0; i < nbox; i++) {
+ drm_clip_rect_t rect;
+ int box_w, box_h;
+ GLint px, py;
+ GLuint stipple[32];
+
+ if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
+ continue;
+
+ /* Now go back to GL coordinates to figure out what subset of
+ * the bitmap we are uploading for this cliprect:
+ */
+ box_w = rect.x2 - rect.x1;
+ box_h = rect.y2 - rect.y1;
+ srcx = rect.x1 - orig_screen_x1;
+ srcy = orig_screen_y2 - rect.y2;
+
+
+#define DY 32
+#define DX 32
+
+ /* Then, finally, chop it all into chunks that can be
+ * digested by hardware:
+ */
+ for (py = 0; py < box_h; py += DY) {
+ for (px = 0; px < box_w; px += DX) {
+ int h = MIN2(DY, box_h - py);
+ int w = MIN2(DX, box_w - px);
+ GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8;
+ GLenum logic_op = ctx->Color.ColorLogicOpEnabled ?
+ ctx->Color.LogicOp : GL_COPY;
+
+ assert(sz <= sizeof(stipple));
+ memset(stipple, 0, sz);
+
+ /* May need to adjust this when padding has been introduced in
+ * sz above:
+ */
+ if (get_bitmap_rect(width, height, unpack,
+ bitmap,
+ srcx + px, srcy + py, w, h,
+ (GLubyte *)stipple,
+ 8,
+ GL_TRUE) == 0)
+ continue;
+
+ /*
+ */
+ intelEmitImmediateColorExpandBlit( intel,
+ dst->cpp,
+ (GLubyte *)stipple,
+ sz,
+ color.ui,
+ dst->pitch,
+ dst->buffer,
+ 0,
+ dst->tiled,
+ rect.x1 + px,
+ rect.y2 - (py + h),
+ w, h,
+ logic_op);
+ }
+ }
+ }
+ intel->need_flush = GL_TRUE;
+ out:
+ intel_batchbuffer_flush(intel->batch);
+ }
+ UNLOCK_HARDWARE(intel);
+
+
+ if (unpack->BufferObj->Name) {
+ /* done with PBO so unmap it now */
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ unpack->BufferObj);
+ }
+
+ return GL_TRUE;
+}
+
+
+
+
+
+/* There are a large number of possible ways to implement bitmap on
+ * this hardware, most of them have some sort of drawback. Here are a
+ * few that spring to mind:
+ *
+ * Blit:
+ * - XY_MONO_SRC_BLT_CMD
+ * - use XY_SETUP_CLIP_BLT for cliprect clipping.
+ * - XY_TEXT_BLT
+ * - XY_TEXT_IMMEDIATE_BLT
+ * - blit per cliprect, subject to maximum immediate data size.
+ * - XY_COLOR_BLT
+ * - per pixel or run of pixels
+ * - XY_PIXEL_BLT
+ * - good for sparse bitmaps
+ *
+ * 3D engine:
+ * - Point per pixel
+ * - Translate bitmap to an alpha texture and render as a quad
+ * - Chop bitmap up into 32x32 squares and render w/polygon stipple.
+ */
+void
+intelBitmap(GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte * pixels)
+{
+ if (do_blit_bitmap(ctx, x, y, width, height,
+ unpack, pixels))
+ return;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
+
+ _swrast_Bitmap(ctx, x, y, width, height, unpack, pixels);
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "image.h"
+#include "state.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_buffers.h"
+#include "intel_blit.h"
+#include "intel_regions.h"
+#include "intel_tris.h"
+#include "intel_pixel.h"
+
+#define FILE_DEBUG_FLAG DEBUG_PIXEL
+
+static struct intel_region *
+copypix_src_region(struct intel_context *intel, GLenum type)
+{
+ switch (type) {
+ case GL_COLOR:
+ return intel_readbuf_region(intel);
+ case GL_DEPTH:
+ /* Don't think this is really possible execpt at 16bpp, when we have no stencil.
+ */
+ if (intel->depth_region && intel->depth_region->cpp == 2)
+ return intel->depth_region;
+ case GL_STENCIL:
+ /* Don't think this is really possible.
+ */
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ /* Does it matter whether it is stencil/depth or depth/stencil?
+ */
+ return intel->depth_region;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Check if any fragment operations are in effect which might effect
+ * glCopyPixels. Differs from intel_check_blit_fragment_ops in that
+ * we allow Scissor.
+ */
+static GLboolean
+intel_check_copypixel_blit_fragment_ops(GLcontext * ctx)
+{
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ /* Could do logicop with the blitter:
+ */
+ return !(ctx->_ImageTransferState ||
+ ctx->Color.AlphaEnabled ||
+ ctx->Depth.Test ||
+ ctx->Fog.Enabled ||
+ ctx->Stencil.Enabled ||
+ !ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3] ||
+ ctx->Texture._EnabledUnits ||
+ ctx->FragmentProgram._Enabled ||
+ ctx->Color.BlendEnabled);
+}
+
+/* Doesn't work for overlapping regions. Could do a double copy or
+ * just fallback.
+ */
+static GLboolean
+do_texture_copypixels(GLcontext * ctx,
+ GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_region *dst = intel_drawbuf_region(intel);
+ struct intel_region *src = copypix_src_region(intel, type);
+ GLenum src_format;
+ GLenum src_type;
+
+ DBG("%s %d,%d %dx%d --> %d,%d\n", __FUNCTION__,
+ srcx, srcy, width, height, dstx, dsty);
+
+ if (!src || !dst || type != GL_COLOR)
+ return GL_FALSE;
+
+ /* Can't handle overlapping regions. Don't have sufficient control
+ * over rasterization to pull it off in-place. Punt on these for
+ * now.
+ *
+ * XXX: do a copy to a temporary.
+ */
+ if (src->buffer == dst->buffer) {
+ drm_clip_rect_t srcbox;
+ drm_clip_rect_t dstbox;
+ drm_clip_rect_t tmp;
+
+ srcbox.x1 = srcx;
+ srcbox.y1 = srcy;
+ srcbox.x2 = srcx + width;
+ srcbox.y2 = srcy + height;
+
+ dstbox.x1 = dstx;
+ dstbox.y1 = dsty;
+ dstbox.x2 = dstx + width * ctx->Pixel.ZoomX;
+ dstbox.y2 = dsty + height * ctx->Pixel.ZoomY;
+
+ DBG("src %d,%d %d,%d\n", srcbox.x1, srcbox.y1, srcbox.x2, srcbox.y2);
+ DBG("dst %d,%d %d,%d (%dx%d) (%f,%f)\n", dstbox.x1, dstbox.y1, dstbox.x2, dstbox.y2,
+ width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+
+ if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) {
+ DBG("%s: regions overlap\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+ }
+
+ intelFlush(&intel->ctx);
+
+ intel->vtbl.install_meta_state(intel);
+
+ /* Is this true? Also will need to turn depth testing on according
+ * to state:
+ */
+ intel->vtbl.meta_no_stencil_write(intel);
+ intel->vtbl.meta_no_depth_write(intel);
+
+ /* Set the 3d engine to draw into the destination region:
+ */
+ intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
+
+ intel->vtbl.meta_import_pixel_state(intel);
+
+ if (src->cpp == 2) {
+ src_format = GL_RGB;
+ src_type = GL_UNSIGNED_SHORT_5_6_5;
+ }
+ else {
+ src_format = GL_BGRA;
+ src_type = GL_UNSIGNED_BYTE;
+ }
+
+ /* Set the frontbuffer up as a large rectangular texture.
+ */
+ if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, 0,
+ src->pitch,
+ src->height, src_format, src_type)) {
+ intel->vtbl.leave_meta_state(intel);
+ return GL_FALSE;
+ }
+
+
+ intel->vtbl.meta_texture_blend_replace(intel);
+
+ LOCK_HARDWARE(intel);
+
+ if (intel->driDrawable->numClipRects) {
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+
+ srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
+
+ srcx += dPriv->x;
+ srcy += dPriv->y;
+
+ /* Clip against the source region. This is the only source
+ * clipping we do. XXX: Just set the texcord wrap mode to clamp
+ * or similar.
+ *
+ */
+ if (0) {
+ GLint orig_x = srcx;
+ GLint orig_y = srcy;
+
+ if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
+ &srcx, &srcy, &width, &height))
+ goto out;
+
+ dstx += srcx - orig_x;
+ dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;
+ }
+
+ /* Just use the regular cliprect mechanism... Does this need to
+ * even hold the lock???
+ */
+ intel->vtbl.meta_draw_quad(intel,
+ dstx,
+ dstx + width * ctx->Pixel.ZoomX,
+ dPriv->h - (dsty + height * ctx->Pixel.ZoomY),
+ dPriv->h - (dsty), 0, /* XXX: what z value? */
+ 0x00ff00ff,
+ srcx, srcx + width, srcy, srcy + height);
+
+ out:
+ intel->vtbl.leave_meta_state(intel);
+ intel_batchbuffer_flush(intel->batch);
+ }
+ UNLOCK_HARDWARE(intel);
+
+ DBG("%s: success\n", __FUNCTION__);
+ return GL_TRUE;
+}
+
+
+
+
+
+/**
+ * CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
+ */
+static GLboolean
+do_blit_copypixels(GLcontext * ctx,
+ GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_region *dst = intel_drawbuf_region(intel);
+ struct intel_region *src = copypix_src_region(intel, type);
+
+ /* Copypixels can be more than a straight copy. Ensure all the
+ * extra operations are disabled:
+ */
+ if (!intel_check_copypixel_blit_fragment_ops(ctx) ||
+ ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
+ return GL_FALSE;
+
+ if (!src || !dst)
+ return GL_FALSE;
+
+
+
+ intelFlush(&intel->ctx);
+
+ LOCK_HARDWARE(intel);
+
+ if (intel->driDrawable->numClipRects) {
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t dest_rect;
+ GLint nbox = dPriv->numClipRects;
+ GLint delta_x = 0;
+ GLint delta_y = 0;
+ GLuint i;
+
+ /* Do scissoring in GL coordinates:
+ */
+ if (ctx->Scissor.Enabled)
+ {
+ GLint x = ctx->Scissor.X;
+ GLint y = ctx->Scissor.Y;
+ GLuint w = ctx->Scissor.Width;
+ GLuint h = ctx->Scissor.Height;
+ GLint dx = dstx - srcx;
+ GLint dy = dsty - srcy;
+
+ if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height))
+ goto out;
+
+ srcx = dstx - dx;
+ srcy = dsty - dy;
+ }
+
+ /* Convert from GL to hardware coordinates:
+ */
+ dsty = dPriv->h - dsty - height;
+ srcy = dPriv->h - srcy - height;
+ dstx += dPriv->x;
+ dsty += dPriv->y;
+ srcx += dPriv->x;
+ srcy += dPriv->y;
+
+ /* Clip against the source region. This is the only source
+ * clipping we do. Dst is clipped with cliprects below.
+ */
+ {
+ delta_x = srcx - dstx;
+ delta_y = srcy - dsty;
+
+ if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
+ &srcx, &srcy, &width, &height))
+ goto out;
+
+ dstx = srcx - delta_x;
+ dsty = srcy - delta_y;
+ }
+
+ dest_rect.x1 = dstx;
+ dest_rect.y1 = dsty;
+ dest_rect.x2 = dstx + width;
+ dest_rect.y2 = dsty + height;
+
+ /* Could do slightly more clipping: Eg, take the intersection of
+ * the existing set of cliprects and those cliprects translated
+ * by delta_x, delta_y:
+ *
+ * This code will not overwrite other windows, but will
+ * introduce garbage when copying from obscured window regions.
+ */
+ for (i = 0; i < nbox; i++) {
+ drm_clip_rect_t rect;
+
+ if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
+ continue;
+
+
+ intelEmitCopyBlit(intel, dst->cpp,
+ src->pitch, src->buffer, 0, src->tiled,
+ dst->pitch, dst->buffer, 0, dst->tiled,
+ rect.x1 + delta_x,
+ rect.y1 + delta_y, /* srcx, srcy */
+ rect.x1, rect.y1, /* dstx, dsty */
+ rect.x2 - rect.x1, rect.y2 - rect.y1,
+ ctx->Color.ColorLogicOpEnabled ?
+ ctx->Color.LogicOp : GL_COPY);
+ }
+
+ out:
+ intel_batchbuffer_flush(intel->batch);
+ }
+ UNLOCK_HARDWARE(intel);
+
+ DBG("%s: success\n", __FUNCTION__);
+ return GL_TRUE;
+}
+
+
+void
+intelCopyPixels(GLcontext * ctx,
+ GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint destx, GLint desty, GLenum type)
+{
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
+ return;
+
+ if (do_texture_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
+ return;
+
+ DBG("fallback to _swrast_CopyPixels\n");
+
+ _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type);
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portionsalloc
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "image.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "bufferobj.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_buffers.h"
+#include "intel_regions.h"
+#include "intel_pixel.h"
+#include "intel_buffer_objects.h"
+#include "intel_tris.h"
+
+
+
+static GLboolean
+do_texture_drawpixels(GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_region *dst = intel_drawbuf_region(intel);
+ struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
+ GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
+ GLuint src_offset;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ intelFlush(&intel->ctx);
+ intel->vtbl.render_start(intel);
+ intel->vtbl.emit_state(intel);
+
+ if (!dst)
+ return GL_FALSE;
+
+ if (src) {
+ if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* PBO only for now:
+ */
+/* _mesa_printf("%s - not PBO\n", __FUNCTION__); */
+ return GL_FALSE;
+ }
+
+ /* There are a couple of things we can't do yet, one of which is
+ * set the correct state for pixel operations when GL texturing is
+ * enabled. That's a pretty rare state and probably not worth the
+ * effort. A completely device-independent version of this may do
+ * more.
+ *
+ * Similarly, we make no attempt to merge metaops processing with
+ * an enabled fragment program, though it would certainly be
+ * possible.
+ */
+ if (!intel_check_meta_tex_fragment_ops(ctx)) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - bad GL fragment state for metaops texture\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ intel->vtbl.install_meta_state(intel);
+
+
+ /* Is this true? Also will need to turn depth testing on according
+ * to state:
+ */
+ intel->vtbl.meta_no_stencil_write(intel);
+ intel->vtbl.meta_no_depth_write(intel);
+
+ /* Set the 3d engine to draw into the destination region:
+ */
+ intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
+
+ intel->vtbl.meta_import_pixel_state(intel);
+
+ src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
+ format, type, 0, 0, 0);
+
+
+ /* Setup the pbo up as a rectangular texture, if possible.
+ *
+ * TODO: This is almost always possible if the i915 fragment
+ * program is adjusted to correctly swizzle the sampled colors.
+ * The major exception is any 24bit texture, like RGB888, for which
+ * there is no hardware support.
+ */
+ if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, src_offset,
+ rowLength, height, format, type)) {
+ intel->vtbl.leave_meta_state(intel);
+ return GL_FALSE;
+ }
+
+ intel->vtbl.meta_texture_blend_replace(intel);
+
+
+ LOCK_HARDWARE(intel);
+
+ if (intel->driDrawable->numClipRects) {
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ GLint srcx, srcy;
+ GLint dstx, dsty;
+
+ dstx = x;
+ dsty = dPriv->h - (y + height);
+
+ srcx = 0; /* skiprows/pixels already done */
+ srcy = 0;
+
+ if (0) {
+ const GLint orig_x = dstx;
+ const GLint orig_y = dsty;
+
+ if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
+ &dstx, &dsty, &width, &height))
+ goto out;
+
+ srcx += dstx - orig_x;
+ srcy += dsty - orig_y;
+ }
+
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("draw %d,%d %dx%d\n", dstx, dsty, width, height);
+
+ /* Must use the regular cliprect mechanism in order to get the
+ * drawing origin set correctly. Otherwise scissor state is in
+ * incorrect coordinate space. Does this even need to hold the
+ * lock???
+ */
+ intel->vtbl.meta_draw_quad(intel,
+ dstx, dstx + width * ctx->Pixel.ZoomX,
+ dPriv->h - (y + height * ctx->Pixel.ZoomY),
+ dPriv->h - (y),
+ -ctx->Current.RasterPos[2] * .5,
+ 0x00ff00ff,
+ srcx, srcx + width, srcy + height, srcy);
+ out:
+ intel->vtbl.leave_meta_state(intel);
+ intel_batchbuffer_flush(intel->batch);
+ }
+ UNLOCK_HARDWARE(intel);
+ return GL_TRUE;
+}
+
+
+
+
+
+/* Pros:
+ * - no waiting for idle before updating framebuffer.
+ *
+ * Cons:
+ * - if upload is by memcpy, this may actually be slower than fallback path.
+ * - uploads the whole image even if destination is clipped
+ *
+ * Need to benchmark.
+ *
+ * Given the questions about performance, implement for pbo's only.
+ * This path is definitely a win if the pbo is already in agp. If it
+ * turns out otherwise, we can add the code necessary to upload client
+ * data to agp space before performing the blit. (Though it may turn
+ * out to be better/simpler just to use the texture engine).
+ */
+static GLboolean
+do_blit_drawpixels(GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_region *dest = intel_drawbuf_region(intel);
+ struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
+ GLuint src_offset;
+ GLuint rowLength;
+ dri_fence *fence = NULL;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s\n", __FUNCTION__);
+
+
+ if (!dest) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - no dest\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ if (src) {
+ /* This validation should be done by core mesa:
+ */
+ if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* PBO only for now:
+ */
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - not PBO\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ if (!intel_check_blit_format(dest, format, type)) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ if (!intel_check_blit_fragment_ops(ctx)) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - bad GL fragment state for blitter\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ if (ctx->Pixel.ZoomX != 1.0F) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+
+ if (unpack->RowLength > 0)
+ rowLength = unpack->RowLength;
+ else
+ rowLength = width;
+
+ if (ctx->Pixel.ZoomY == -1.0F) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
+ return GL_FALSE; /* later */
+ y -= height;
+ }
+ else if (ctx->Pixel.ZoomY == 1.0F) {
+ rowLength = -rowLength;
+ }
+ else {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
+ format, type, 0, 0, 0);
+
+ intelFlush(&intel->ctx);
+ LOCK_HARDWARE(intel);
+
+ if (intel->driDrawable->numClipRects) {
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ int nbox = dPriv->numClipRects;
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t rect;
+ drm_clip_rect_t dest_rect;
+ dri_bo *src_buffer = intel_bufferobj_buffer(intel, src, INTEL_READ);
+ int i;
+
+ dest_rect.x1 = dPriv->x + x;
+ dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
+ dest_rect.x2 = dest_rect.x1 + width;
+ dest_rect.y2 = dest_rect.y1 + height;
+
+ for (i = 0; i < nbox; i++) {
+ if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
+ continue;
+
+ intelEmitCopyBlit(intel,
+ dest->cpp,
+ rowLength, src_buffer, src_offset, GL_FALSE,
+ dest->pitch, dest->buffer, 0, dest->tiled,
+ rect.x1 - dest_rect.x1,
+ rect.y2 - dest_rect.y2,
+ rect.x1,
+ rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1,
+ ctx->Color.ColorLogicOpEnabled ?
+ ctx->Color.LogicOp : GL_COPY);
+ }
+ intel_batchbuffer_flush(intel->batch);
+ fence = intel->batch->last_fence;
+ dri_fence_reference(fence);
+ }
+ UNLOCK_HARDWARE(intel);
+
+ if (fence) {
+ dri_fence_wait(fence);
+ dri_fence_unreference(fence);
+ }
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - DONE\n", __FUNCTION__);
+
+ return GL_TRUE;
+}
+
+
+
+void
+intelDrawPixels(GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format,
+ GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels)
+{
+ if (do_blit_drawpixels(ctx, x, y, width, height, format, type,
+ unpack, pixels))
+ return;
+
+ if (do_texture_drawpixels(ctx, x, y, width, height, format, type,
+ unpack, pixels))
+ return;
+
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
+
+ if (ctx->FragmentProgram._Current == ctx->FragmentProgram._TexEnvProgram) {
+ /*
+ * We don't want the i915 texenv program to be applied to DrawPixels.
+ * This is really just a performance optimization (mesa will other-
+ * wise happily run the fragment program on each pixel in the image).
+ */
+ struct gl_fragment_program *fpSave = ctx->FragmentProgram._Current;
+ /* can't just set current frag prog to 0 here as on buffer resize
+ we'll get new state checks which will segfault. Remains a hack. */
+ ctx->FragmentProgram._Current = NULL;
+ ctx->FragmentProgram._UseTexEnvProgram = GL_FALSE;
+ ctx->FragmentProgram._Active = GL_FALSE;
+ _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels );
+ ctx->FragmentProgram._Current = fpSave;
+ ctx->FragmentProgram._UseTexEnvProgram = GL_TRUE;
+ ctx->FragmentProgram._Active = GL_TRUE;
+ }
+ else {
+ _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels );
+ }
+}