Add offset and pitch fields to intelRegion. Remove frontOffset, frontPitch,
[mesa.git] / src / mesa / drivers / dri / i915 / intel_pixel.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "glheader.h"
29 #include "enums.h"
30 #include "mtypes.h"
31 #include "macros.h"
32 #include "swrast/swrast.h"
33
34 #include "intel_screen.h"
35 #include "intel_context.h"
36 #include "intel_ioctl.h"
37 #include "intel_batchbuffer.h"
38
39
40
41 static GLboolean
42 check_color( const GLcontext *ctx, GLenum type, GLenum format,
43 const struct gl_pixelstore_attrib *packing,
44 const void *pixels, GLint sz, GLint pitch )
45 {
46 intelContextPtr intel = INTEL_CONTEXT(ctx);
47 GLuint cpp = intel->intelScreen->cpp;
48
49 if (INTEL_DEBUG & DEBUG_PIXEL)
50 fprintf(stderr, "%s\n", __FUNCTION__);
51
52 if ( (pitch & 63) ||
53 ctx->_ImageTransferState ||
54 packing->SwapBytes ||
55 packing->LsbFirst) {
56 if (INTEL_DEBUG & DEBUG_PIXEL)
57 fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
58 return GL_FALSE;
59 }
60
61 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
62 cpp == 4 &&
63 format == GL_BGRA ) {
64 if (INTEL_DEBUG & DEBUG_PIXEL)
65 fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
66 return GL_TRUE;
67 }
68
69 if (INTEL_DEBUG & DEBUG_PIXEL)
70 fprintf(stderr, "%s: failed\n", __FUNCTION__);
71
72 return GL_FALSE;
73 }
74
75 static GLboolean
76 check_color_per_fragment_ops( const GLcontext *ctx )
77 {
78 int result;
79 result = (!( ctx->Color.AlphaEnabled ||
80 ctx->Depth.Test ||
81 ctx->Fog.Enabled ||
82 ctx->Scissor.Enabled ||
83 ctx->Stencil.Enabled ||
84 !ctx->Color.ColorMask[0] ||
85 !ctx->Color.ColorMask[1] ||
86 !ctx->Color.ColorMask[2] ||
87 !ctx->Color.ColorMask[3] ||
88 ctx->Color.ColorLogicOpEnabled ||
89 ctx->Texture._EnabledUnits
90 ) &&
91 ctx->Current.RasterPosValid);
92
93 return result;
94 }
95
96
97
98 static GLboolean
99 clip_pixelrect( const GLcontext *ctx,
100 const GLframebuffer *buffer,
101 GLint *x, GLint *y,
102 GLsizei *width, GLsizei *height,
103 GLint *size )
104 {
105 intelContextPtr intel = INTEL_CONTEXT(ctx);
106
107 /* left clipping */
108 if (*x < buffer->_Xmin) {
109 *width -= (buffer->_Xmin - *x);
110 *x = buffer->_Xmin;
111 }
112
113 /* right clipping */
114 if (*x + *width > buffer->_Xmax)
115 *width -= (*x + *width - buffer->_Xmax - 1);
116
117 if (*width <= 0)
118 return GL_FALSE;
119
120 /* bottom clipping */
121 if (*y < buffer->_Ymin) {
122 *height -= (buffer->_Ymin - *y);
123 *y = buffer->_Ymin;
124 }
125
126 /* top clipping */
127 if (*y + *height > buffer->_Ymax)
128 *height -= (*y + *height - buffer->_Ymax - 1);
129
130 if (*height <= 0)
131 return GL_FALSE;
132
133 *size = ((*y + *height - 1) * intel->intelScreen->front.pitch +
134 (*x + *width - 1) * intel->intelScreen->cpp);
135
136 return GL_TRUE;
137 }
138
139 static GLboolean
140 intelTryReadPixels( GLcontext *ctx,
141 GLint x, GLint y, GLsizei width, GLsizei height,
142 GLenum format, GLenum type,
143 const struct gl_pixelstore_attrib *pack,
144 GLvoid *pixels )
145 {
146 intelContextPtr intel = INTEL_CONTEXT(ctx);
147 GLint size = 0;
148 GLint pitch = pack->RowLength ? pack->RowLength : width;
149
150 if (INTEL_DEBUG & DEBUG_PIXEL)
151 fprintf(stderr, "%s\n", __FUNCTION__);
152
153 /* Only accelerate reading to agp buffers.
154 */
155 if ( !intelIsAgpMemory(intel, pixels,
156 pitch * height * intel->intelScreen->cpp ) ) {
157 if (INTEL_DEBUG & DEBUG_PIXEL)
158 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
159 return GL_FALSE;
160 }
161
162 /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
163 * blitter:
164 */
165 if (!pack->Invert) {
166 if (INTEL_DEBUG & DEBUG_PIXEL)
167 fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
168 return GL_FALSE;
169 }
170
171 if (!check_color(ctx, type, format, pack, pixels, size, pitch))
172 return GL_FALSE;
173
174 switch ( intel->intelScreen->cpp ) {
175 case 4:
176 break;
177 default:
178 return GL_FALSE;
179 }
180
181
182 /* Although the blits go on the command buffer, need to do this and
183 * fire with lock held to guarentee cliprects and drawOffset are
184 * correct.
185 *
186 * This is an unusual situation however, as the code which flushes
187 * a full command buffer expects to be called unlocked. As a
188 * workaround, immediately flush the buffer on aquiring the lock.
189 */
190 intelFlush( &intel->ctx );
191 LOCK_HARDWARE( intel );
192 {
193 __DRIdrawablePrivate *dPriv = intel->driDrawable;
194 int nbox = dPriv->numClipRects;
195 int src_offset = intel->drawOffset;
196 int src_pitch = intel->intelScreen->front.pitch;
197 int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
198 drm_clip_rect_t *box = dPriv->pClipRects;
199 int i;
200
201 if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
202 &size)) {
203 UNLOCK_HARDWARE( intel );
204 if (INTEL_DEBUG & DEBUG_PIXEL)
205 fprintf(stderr, "%s totally clipped -- nothing to do\n",
206 __FUNCTION__);
207 return GL_TRUE;
208 }
209
210
211 y = dPriv->h - y - height;
212 x += dPriv->x;
213 y += dPriv->y;
214
215
216 if (INTEL_DEBUG & DEBUG_PIXEL)
217 fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
218 src_pitch, pitch);
219
220 for (i = 0 ; i < nbox ; i++)
221 {
222 GLint bx = box[i].x1;
223 GLint by = box[i].y1;
224 GLint bw = box[i].x2 - bx;
225 GLint bh = box[i].y2 - by;
226
227 if (bx < x) bw -= x - bx, bx = x;
228 if (by < y) bh -= y - by, by = y;
229 if (bx + bw > x + width) bw = x + width - bx;
230 if (by + bh > y + height) bh = y + height - by;
231 if (bw <= 0) continue;
232 if (bh <= 0) continue;
233
234 intelEmitCopyBlitLocked( intel,
235 intel->intelScreen->cpp,
236 src_pitch, src_offset,
237 pitch, dst_offset,
238 bx, by,
239 bx - x, by - y,
240 bw, bh );
241 }
242 }
243 UNLOCK_HARDWARE( intel );
244 intelFinish( &intel->ctx );
245
246 return GL_TRUE;
247 }
248
249 static void
250 intelReadPixels( GLcontext *ctx,
251 GLint x, GLint y, GLsizei width, GLsizei height,
252 GLenum format, GLenum type,
253 const struct gl_pixelstore_attrib *pack,
254 GLvoid *pixels )
255 {
256 if (INTEL_DEBUG & DEBUG_PIXEL)
257 fprintf(stderr, "%s\n", __FUNCTION__);
258
259 if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,
260 pixels))
261 _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,
262 pixels);
263 }
264
265
266
267
268 static void do_draw_pix( GLcontext *ctx,
269 GLint x, GLint y, GLsizei width, GLsizei height,
270 GLint pitch,
271 const void *pixels,
272 GLuint dest )
273 {
274 intelContextPtr intel = INTEL_CONTEXT(ctx);
275 __DRIdrawablePrivate *dPriv = intel->driDrawable;
276 drm_clip_rect_t *box = dPriv->pClipRects;
277 int nbox = dPriv->numClipRects;
278 int i;
279 int size;
280 int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
281 int src_pitch = pitch;
282
283 if (INTEL_DEBUG & DEBUG_PIXEL)
284 fprintf(stderr, "%s\n", __FUNCTION__);
285
286 intelFlush( &intel->ctx );
287 LOCK_HARDWARE( intel );
288 if (ctx->DrawBuffer)
289 {
290 y -= height; /* cope with pixel zoom */
291
292 if (!clip_pixelrect(ctx, ctx->DrawBuffer,
293 &x, &y, &width, &height,
294 &size)) {
295 UNLOCK_HARDWARE( intel );
296 return;
297 }
298
299 y = dPriv->h - y - height; /* convert from gl to hardware coords */
300 x += dPriv->x;
301 y += dPriv->y;
302
303
304 for (i = 0 ; i < nbox ; i++ )
305 {
306 GLint bx = box[i].x1;
307 GLint by = box[i].y1;
308 GLint bw = box[i].x2 - bx;
309 GLint bh = box[i].y2 - by;
310
311 if (bx < x) bw -= x - bx, bx = x;
312 if (by < y) bh -= y - by, by = y;
313 if (bx + bw > x + width) bw = x + width - bx;
314 if (by + bh > y + height) bh = y + height - by;
315 if (bw <= 0) continue;
316 if (bh <= 0) continue;
317
318 intelEmitCopyBlitLocked( intel,
319 intel->intelScreen->cpp,
320 src_pitch, src_offset,
321 intel->intelScreen->front.pitch,
322 intel->drawOffset,
323 bx - x, by - y,
324 bx, by,
325 bw, bh );
326 }
327 }
328 UNLOCK_HARDWARE( intel );
329 intelFinish( &intel->ctx );
330 }
331
332
333
334
335 static GLboolean
336 intelTryDrawPixels( GLcontext *ctx,
337 GLint x, GLint y, GLsizei width, GLsizei height,
338 GLenum format, GLenum type,
339 const struct gl_pixelstore_attrib *unpack,
340 const GLvoid *pixels )
341 {
342 intelContextPtr intel = INTEL_CONTEXT(ctx);
343 GLint pitch = unpack->RowLength ? unpack->RowLength : width;
344 GLuint dest;
345 GLuint cpp = intel->intelScreen->cpp;
346 GLint size = width * pitch * cpp;
347
348 if (INTEL_DEBUG & DEBUG_PIXEL)
349 fprintf(stderr, "%s\n", __FUNCTION__);
350
351 switch (format) {
352 case GL_RGB:
353 case GL_RGBA:
354 case GL_BGRA:
355 dest = intel->drawOffset;
356
357 /* Planemask doesn't have full support in blits.
358 */
359 if (!ctx->Color.ColorMask[RCOMP] ||
360 !ctx->Color.ColorMask[GCOMP] ||
361 !ctx->Color.ColorMask[BCOMP] ||
362 !ctx->Color.ColorMask[ACOMP]) {
363 if (INTEL_DEBUG & DEBUG_PIXEL)
364 fprintf(stderr, "%s: planemask\n", __FUNCTION__);
365 return GL_FALSE;
366 }
367
368 /* Can't do conversions on agp reads/draws.
369 */
370 if ( !intelIsAgpMemory( intel, pixels, size ) ) {
371 if (INTEL_DEBUG & DEBUG_PIXEL)
372 fprintf(stderr, "%s: not agp memory\n", __FUNCTION__);
373 return GL_FALSE;
374 }
375
376 if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
377 return GL_FALSE;
378 }
379 if (!check_color_per_fragment_ops(ctx)) {
380 return GL_FALSE;
381 }
382
383 if (ctx->Pixel.ZoomX != 1.0F ||
384 ctx->Pixel.ZoomY != -1.0F)
385 return GL_FALSE;
386 break;
387
388 default:
389 return GL_FALSE;
390 }
391
392 if ( intelIsAgpMemory(intel, pixels, size) )
393 {
394 do_draw_pix( ctx, x, y, width, height, pitch, pixels,
395 dest );
396 return GL_TRUE;
397 }
398 else if (0)
399 {
400 /* Pixels is in regular memory -- get dma buffers and perform
401 * upload through them. No point doing this for regular uploads
402 * but once we remove some of the restrictions above (colormask,
403 * pixelformat conversion, zoom?, etc), this could be a win.
404 */
405 }
406 else
407 return GL_FALSE;
408 }
409
410 static void
411 intelDrawPixels( GLcontext *ctx,
412 GLint x, GLint y, GLsizei width, GLsizei height,
413 GLenum format, GLenum type,
414 const struct gl_pixelstore_attrib *unpack,
415 const GLvoid *pixels )
416 {
417 if (INTEL_DEBUG & DEBUG_PIXEL)
418 fprintf(stderr, "%s\n", __FUNCTION__);
419
420 if (!intelTryDrawPixels( ctx, x, y, width, height, format, type,
421 unpack, pixels ))
422 _swrast_DrawPixels( ctx, x, y, width, height, format, type,
423 unpack, pixels );
424 }
425
426
427
428
429 /**
430 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
431 * for the color buffer. Don't support zooming, pixel transfer, etc.
432 * We do support copying from one window to another, ala glXMakeCurrentRead.
433 */
434 static void
435 intelCopyPixels( GLcontext *ctx,
436 GLint srcx, GLint srcy, GLsizei width, GLsizei height,
437 GLint destx, GLint desty, GLenum type )
438 {
439 #if 0
440 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
441 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
442 XMesaDisplay *dpy = xmesa->xm_visual->display;
443 const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
444 const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
445 const XMesaGC gc = xmesa->xm_draw_buffer->gc;
446
447 ASSERT(dpy);
448 ASSERT(gc);
449
450 if (drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
451 readBuffer &&
452 type == GL_COLOR &&
453 (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
454 ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
455 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
456 ctx->Pixel.ZoomY == 1.0) {
457 /* Note: we don't do any special clipping work here. We could,
458 * but X will do it for us.
459 */
460 srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
461 desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
462 XCopyArea(dpy, readBuffer, drawBuffer, gc,
463 srcx, srcy, width, height, destx, desty);
464 }
465 #else
466 _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
467 #endif
468 }
469
470
471
472
473 void intelInitPixelFuncs( struct dd_function_table *functions )
474 {
475 /* Pixel path fallbacks.
476 */
477 functions->Accum = _swrast_Accum;
478 functions->Bitmap = _swrast_Bitmap;
479 functions->CopyPixels = intelCopyPixels;
480
481 if (!getenv("INTEL_NO_BLITS")) {
482 functions->ReadPixels = intelReadPixels;
483 functions->DrawPixels = intelDrawPixels;
484 }
485 else {
486 functions->ReadPixels = _swrast_ReadPixels;
487 functions->DrawPixels = _swrast_DrawPixels;
488 }
489 }