Minor fixes to comments.
[AROS.git] / rom / graphics / gfxfuncsupport.c
blob1a5f0a1d8574ed5012052bb16ddc0d289c3ed816
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #include <cybergraphx/cybergraphics.h>
9 #include <graphics/rpattr.h>
10 #include <proto/layers.h>
11 #include <proto/exec.h>
12 #include <proto/graphics.h>
13 #include <proto/oop.h>
14 #include <clib/macros.h>
16 #include "graphics_intern.h"
17 #include "objcache.h"
18 #include "intregions.h"
19 #include "gfxfuncsupport.h"
20 #include "graphics_driver.h"
22 #define DEBUG 0
23 #include <aros/debug.h>
25 #define DEBUG_PLANARBM(x)
27 #define LayersBase (struct LayersBase *)(GfxBase->gb_LayersBase)
29 /****************************************************************************************/
31 OOP_Object *get_planarbm_object(struct BitMap *bitmap, struct GfxBase *GfxBase)
33 OOP_Object *pbm_obj;
35 DEBUG_PLANARBM(bug("get_planarbm_object()\n"));
36 pbm_obj = obtain_cache_object(CDD(GfxBase)->planarbm_cache, GfxBase);
38 if (NULL != pbm_obj)
41 DEBUG_PLANARBM(bug("Got cache object %p, class=%s, instoffset=%d\n"
42 , pbm_obj
43 , OOP_OCLASS(pbm_obj)->ClassNode.ln_Name
44 , OOP_OCLASS(pbm_obj)->InstOffset
45 ));
47 if (!HIDD_PlanarBM_SetBitMap(pbm_obj, bitmap))
49 DEBUG_PLANARBM(bug("!!! get_planarbm_object: HIDD_PlanarBM_SetBitMap FAILED !!!\n"));
50 release_cache_object(CDD(GfxBase)->planarbm_cache, pbm_obj, GfxBase);
51 pbm_obj = NULL;
55 else
57 DEBUG_PLANARBM(bug("!!! get_planarbm_object: obtain_cache_object FAILED !!!\n"));
60 return pbm_obj;
63 /****************************************************************************************/
65 static ULONG CallRenderFunc(RENDERFUNC render_func, APTR funcdata, WORD srcx, WORD srcy,
66 struct BitMap *bm, OOP_Object *gc, struct Rectangle *rect, BOOL do_update,
67 struct GfxBase *GfxBase)
69 OOP_Object *bm_obj = OBTAIN_HIDD_BM(bm);
70 ULONG pixwritten;
72 if (!bm_obj)
73 return 0;
75 pixwritten = render_func(funcdata, srcx, srcy, bm_obj, gc, rect, GfxBase);
77 if (do_update)
78 update_bitmap(bm, bm_obj, rect->MinX, rect->MinY,
79 rect->MaxX - rect->MinX + 1, rect->MaxY - rect->MinY + 1,
80 GfxBase);
82 RELEASE_HIDD_BM(bm_obj, bm);
83 return pixwritten;
86 ULONG do_render_func(struct RastPort *rp, Point *src, struct Rectangle *rr,
87 RENDERFUNC render_func, APTR funcdata,
88 BOOL do_update, BOOL get_special_info, struct GfxBase *GfxBase)
90 OOP_Object *gc = GetDriverData(rp, GfxBase);
92 return do_render_with_gc(rp, src, rr, render_func, funcdata, gc, do_update, get_special_info, GfxBase);
96 * GetDriverData() resets the GC to RastPort's values.
97 * This is another entry point which avoids that. Use it if you have already set up GC.
99 ULONG do_render_with_gc(struct RastPort *rp, Point *src, struct Rectangle *rr,
100 RENDERFUNC render_func, APTR funcdata, OOP_Object *gc,
101 BOOL do_update, BOOL get_special_info, struct GfxBase *GfxBase)
104 struct BitMap *bm = rp->BitMap;
105 struct Layer *L = rp->Layer;
106 struct Rectangle rp_clip_rectangle;
107 BOOL have_rp_cliprectangle;
108 WORD srcx, srcy;
109 LONG pixwritten = 0;
111 if (NULL != src)
113 srcx = src->x;
114 srcy = src->y;
115 } else
117 srcx = 0;
118 srcy = 0;
121 if (NULL == L)
123 /* No layer, probably a screen, but may be a user inited bitmap */
124 struct Rectangle torender = *rr;
126 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
127 if (have_rp_cliprectangle && !(_AndRectRect(rr, &rp_clip_rectangle, &torender)))
129 return 0;
132 srcx += (torender.MinX - rr->MinX);
133 srcy += (torender.MinY - rr->MinY);
135 if (get_special_info)
137 RSI(funcdata)->curbm = rp->BitMap;
140 pixwritten = CallRenderFunc(render_func, funcdata, srcx, srcy,
141 bm, gc, &torender, do_update, GfxBase);
143 else
145 struct ClipRect *CR;
146 WORD xrel;
147 WORD yrel;
148 struct Rectangle torender, intersect;
150 LockLayerRom(L);
152 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
154 xrel = L->bounds.MinX;
155 yrel = L->bounds.MinY;
157 torender.MinX = rr->MinX + xrel - L->Scroll_X;
158 torender.MinY = rr->MinY + yrel - L->Scroll_Y;
159 torender.MaxX = rr->MaxX + xrel - L->Scroll_X;
160 torender.MaxY = rr->MaxY + yrel - L->Scroll_Y;
162 CR = L->ClipRect;
164 for (;NULL != CR; CR = CR->Next)
166 D(bug("Cliprect (%d, %d, %d, %d), lobs=%p\n",
167 CR->bounds.MinX, CR->bounds.MinY, CR->bounds.MaxX, CR->bounds.MaxY,
168 CR->lobs));
170 /* Does this cliprect intersect with area to rectfill ? */
171 if (_AndRectRect(&CR->bounds, &torender, &intersect))
173 if (!have_rp_cliprectangle || _AndRectRect(&rp_clip_rectangle, &intersect, &intersect))
175 WORD xoffset, yoffset;
177 xoffset = intersect.MinX - torender.MinX;
178 yoffset = intersect.MinY - torender.MinY;
180 if (NULL == CR->lobs)
182 if (get_special_info)
184 RSI(funcdata)->curbm = bm;
187 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
188 bm, gc, &intersect, do_update, GfxBase);
190 else
192 /* Render into offscreen cliprect bitmap */
193 if (L->Flags & LAYERSIMPLE)
194 continue;
195 else if (L->Flags & LAYERSUPER)
197 D(bug("do_render_func(): Superbitmap not handled yet\n"));
199 else
202 if (get_special_info)
204 RSI(funcdata)->curbm = CR->BitMap;
207 intersect.MinX = intersect.MinX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
208 intersect.MinY = intersect.MinY - CR->bounds.MinY;
209 intersect.MaxX = intersect.MaxX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
210 intersect.MaxY = intersect.MaxY - CR->bounds.MinY;
212 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
213 CR->BitMap, gc, &intersect, do_update, GfxBase);
216 } /* if (CR->lobs == NULL) */
218 } /* if it also intersects with possible rastport clip rectangle */
220 } /* if (cliprect intersects with area to render into) */
222 } /* for (each cliprect in the layer) */
224 UnlockLayerRom(L);
225 } /* if (rp->Layer) */
227 return pixwritten;
230 /****************************************************************************************/
232 static LONG CallPixelFunc(PIXELFUNC render_func, APTR funcdata, struct BitMap *bm, OOP_Object *gc,
233 WORD x, WORD y, BOOL do_update, struct GfxBase *GfxBase)
235 OOP_Object *bm_obj = OBTAIN_HIDD_BM(bm);
236 LONG retval;
238 if (!bm_obj)
239 return -1;
241 retval = render_func(funcdata, bm_obj, gc, x, y, GfxBase);
243 if (do_update)
244 update_bitmap(bm, bm_obj, x, y, 1, 1, GfxBase);
246 RELEASE_HIDD_BM(bm_obj, bm);
247 return retval;
250 ULONG do_pixel_func(struct RastPort *rp
251 , WORD x, WORD y
252 , PIXELFUNC render_func
253 , APTR funcdata
254 , BOOL do_update
255 , struct GfxBase *GfxBase)
257 struct BitMap *bm = rp->BitMap;
258 struct Layer *L = rp->Layer;
259 OOP_Object *gc;
260 struct Rectangle rp_clip_rectangle;
261 BOOL have_rp_cliprectangle;
262 ULONG retval = -1;
264 gc = GetDriverData(rp, GfxBase);
266 if (NULL == L)
268 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
269 if (have_rp_cliprectangle && !_IsPointInRect(&rp_clip_rectangle, x, y))
271 return -1;
274 #if 0 /* With enabled BITMAP_CLIPPING this will be done automatically */
275 OOP_GetAttr(bm_obj, aHidd_BitMap_Width, &width);
276 OOP_GetAttr(bm_obj, aHidd_BitMap_Height, &height);
278 /* Check whether we it is inside the rastport */
279 if ( x < 0
280 || x >= width
281 || y < 0
282 || y >= height)
284 return -1;
286 #endif
288 /* This is a screen */
289 retval = CallPixelFunc(render_func, funcdata, bm, gc, x, y, do_update, GfxBase);
291 else
293 struct ClipRect *CR;
294 WORD absx, absy;
296 LockLayerRom( L );
298 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
300 CR = L->ClipRect;
302 absx = x + L->bounds.MinX - L->Scroll_X;
303 absy = y + L->bounds.MinY - L->Scroll_Y;
305 for (;NULL != CR; CR = CR->Next)
308 if ( absx >= CR->bounds.MinX
309 && absy >= CR->bounds.MinY
310 && absx <= CR->bounds.MaxX
311 && absy <= CR->bounds.MaxY )
314 if (!have_rp_cliprectangle || _IsPointInRect(&rp_clip_rectangle, absx, absy))
316 if (NULL == CR->lobs)
318 retval = CallPixelFunc(render_func, funcdata, bm, gc,
319 absx, absy, do_update, GfxBase);
321 else
323 /* This is the tricky one: render into offscreen cliprect bitmap */
324 if (L->Flags & LAYERSIMPLE)
326 /* We cannot do anything */
327 retval = 0;
330 else if (L->Flags & LAYERSUPER)
332 D(bug("driver_WriteRGBPixel(): Superbitmap not handled yet\n"));
334 else
336 retval = CallPixelFunc(render_func, funcdata, CR->BitMap, gc,
337 absx - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX),
338 absy - CR->bounds.MinY,
339 do_update, GfxBase);
340 } /* If (SMARTREFRESH cliprect) */
342 } /* if (intersecton inside hidden cliprect) */
344 } /* if point is also inside possible rastport clip rectangle */
346 /* The pixel was found and put inside one of the cliprects, just exit */
347 break;
349 } /* if (cliprect intersects with area we want to draw to) */
351 } /* while (cliprects to examine) */
352 UnlockLayerRom( L );
355 return retval;
358 /****************************************************************************************/
360 ULONG fillrect_render(APTR funcdata, WORD srcx, WORD srcy,
361 OOP_Object *dstbm_obj, OOP_Object *dst_gc,
362 struct Rectangle *rect, struct GfxBase *GfxBase)
364 HIDD_BM_FillRect(dstbm_obj, dst_gc, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY);
366 return (rect->MaxX - rect->MinX + 1) * (rect->MaxY - rect->MinY + 1);
369 /****************************************************************************************/
371 LONG fillrect_pendrmd(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
372 HIDDT_Pixel pix, HIDDT_DrawMode drmd, BOOL do_update, struct GfxBase *GfxBase)
374 OOP_Object *gc;
375 struct Rectangle rr;
377 gc = GetDriverData(rp, GfxBase);
378 GC_FG(gc) = pix;
379 GC_DRMD(gc) = drmd;
381 rr.MinX = x1;
382 rr.MinY = y1;
383 rr.MaxX = x2;
384 rr.MaxY = y2;
386 return do_render_with_gc(rp, NULL, &rr, fillrect_render, NULL, gc, do_update, FALSE, GfxBase);
389 /****************************************************************************************/
391 BOOL int_bltbitmap(struct BitMap *srcBitMap, OOP_Object *srcbm_obj, WORD xSrc, WORD ySrc,
392 struct BitMap *dstBitMap, OOP_Object *dstbm_obj, WORD xDest, WORD yDest,
393 WORD xSize, WORD ySize, ULONG minterm, OOP_Object *gfxhidd, OOP_Object *gc,
394 struct GfxBase *GfxBase)
396 HIDDT_DrawMode drmd;
398 ULONG srcflags = 0;
399 ULONG dstflags = 0;
401 BOOL src_colmap_set = FALSE;
402 BOOL dst_colmap_set = FALSE;
403 BOOL success = TRUE;
404 BOOL colmaps_ok = TRUE;
406 drmd = MINTERM_TO_GCDRMD(minterm);
408 /* We must lock any HIDD_BM_SetColorMap calls */
409 LOCK_BLIT
411 /* Try to get a CLUT for the bitmaps */
412 if (IS_HIDD_BM(srcBitMap))
414 //bug("driver_intbltbitmap: source is hidd bitmap\n");
415 if (NULL != HIDD_BM_COLMAP(srcBitMap))
417 //bug("driver_intbltbitmap: source has colormap\n");
418 srcflags |= FLG_HASCOLMAP;
420 srcflags |= GET_COLMOD_FLAGS(srcBitMap);
422 else
424 //bug("driver_intbltbitmap: source is amiga bitmap\n");
425 /* Amiga BM */
426 srcflags |= FLG_PALETTE;
429 if (IS_HIDD_BM(dstBitMap))
431 //bug("driver_intbltbitmap: dest is hidd bitmap\n");
432 if (NULL != HIDD_BM_COLMAP(dstBitMap))
434 //bug("driver_intbltbitmap: dest has colormap\n");
435 dstflags |= FLG_HASCOLMAP;
437 dstflags |= GET_COLMOD_FLAGS(dstBitMap);
439 else
441 //bug("driver_intbltbitmap: dest is amiga bitmap\n");
442 /* Amiga BM */
443 dstflags |= FLG_PALETTE;
446 if ( (srcflags == FLG_PALETTE || srcflags == FLG_STATICPALETTE))
448 /* palettized with no colmap. Neew to get a colmap from dest*/
449 if (dstflags == FLG_TRUECOLOR)
452 D(bug("!!! NO WAY GETTING PALETTE FOR src IN BltBitMap\n"));
453 colmaps_ok = FALSE;
454 success = FALSE;
457 else if (dstflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
460 /* Use the dest colmap for src */
461 HIDD_BM_SetColorMap(srcbm_obj, HIDD_BM_COLMAP(dstBitMap));
463 src_colmap_set = TRUE;
466 bug("Colormap:\n");
468 ULONG idx;
469 for (idx = 0; idx < 256; idx ++)
470 bug("[%d]=%d ", idx, HIDD_CM_GetPixel(HIDD_BM_COLMAP(dstBitMap), idx));
476 if ( (dstflags == FLG_PALETTE || dstflags == FLG_STATICPALETTE))
478 /* palettized with no pixtab. Nees to get a pixtab from dest*/
479 if (srcflags == FLG_TRUECOLOR)
481 D(bug("!!! NO WAY GETTING PALETTE FOR dst IN BltBitMap\n"));
482 colmaps_ok = FALSE;
483 success = FALSE;
486 else if (srcflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
489 /* Use the src colmap for dst */
490 HIDD_BM_SetColorMap(dstbm_obj, HIDD_BM_COLMAP(srcBitMap));
492 dst_colmap_set = TRUE;
496 if (colmaps_ok)
498 /* We need special treatment with drawmode Clear and
499 truecolor bitmaps, in order to set it to
500 colormap[0] instead of just 0
502 if ( (drmd == vHidd_GC_DrawMode_Clear)
503 && ( (dstflags & (FLG_TRUECOLOR | FLG_HASCOLMAP)) == (FLG_TRUECOLOR | FLG_HASCOLMAP) ))
506 HIDDT_DrawMode old_drmd;
507 IPTR old_fg;
509 struct TagItem frtags[] =
511 { aHidd_GC_Foreground , 0 },
512 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
513 { TAG_DONE }
516 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
517 OOP_GetAttr(gc, aHidd_GC_Foreground, &old_fg);
519 frtags[0].ti_Data = HIDD_BM_PIXTAB(dstBitMap)[0];
520 frtags[1].ti_Data = vHidd_GC_DrawMode_Copy;
522 OOP_SetAttrs(gc, frtags);
524 HIDD_BM_FillRect(dstbm_obj, gc
525 , xDest, yDest
526 , xDest + xSize - 1
527 , yDest + ySize - 1
530 frtags[0].ti_Data = old_fg;
531 frtags[1].ti_Data = old_drmd;
534 else
536 HIDDT_DrawMode old_drmd;
538 struct TagItem cbtags[] =
540 { aHidd_GC_DrawMode, 0 },
541 { TAG_DONE }
544 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
546 cbtags[0].ti_Data = drmd;
548 OOP_SetAttrs(gc, cbtags);
549 HIDD_Gfx_CopyBox(gfxhidd
550 , srcbm_obj
551 , xSrc, ySrc
552 , dstbm_obj
553 , xDest, yDest
554 , xSize, ySize
555 , gc
558 cbtags[0].ti_Data = drmd;
559 OOP_SetAttrs(gc, cbtags);
562 } /* if (colmaps_ok) */
564 if (src_colmap_set)
565 HIDD_BM_SetColorMap(srcbm_obj, NULL);
567 if (dst_colmap_set)
568 HIDD_BM_SetColorMap(dstbm_obj, NULL);
570 ULOCK_BLIT
572 return success;
576 /****************************************************************************************/
578 struct wp8_render_data
580 UBYTE *array;
581 ULONG modulo;
582 HIDDT_PixelLUT *pixlut;
585 static ULONG wp8_render(APTR wp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
586 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
588 struct wp8_render_data *wp8rd = wp8r_data;
589 WORD width = rect->MaxX - rect->MinX + 1;
590 WORD height = rect->MaxY - rect->MinY + 1;
592 HIDD_BM_PutImageLUT(dstbm_obj, dst_gc,
593 wp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wp8rd->modulo), wp8rd->modulo,
594 rect->MinX, rect->MinY, width, height, wp8rd->pixlut);
596 return width * height;
599 /****************************************************************************************/
601 LONG write_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
602 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
603 HIDDT_PixelLUT *pixlut, BOOL do_update, struct GfxBase *GfxBase)
605 struct wp8_render_data wp8rd;
606 struct Rectangle rr;
607 OOP_Object *gc;
608 HIDDT_PixelLUT bm_lut;
610 /* If we haven't got a LUT, we obtain it from the bitmap */
611 if ((!pixlut) && IS_HIDD_BM(rp->BitMap))
613 bm_lut.entries = AROS_PALETTE_SIZE;
614 bm_lut.pixels = HIDD_BM_PIXTAB(rp->BitMap);
615 pixlut = &bm_lut;
617 #ifdef RTG_SANITY_CHECK
618 if ((!bm_lut.pixels) && (HIDD_BM_REALDEPTH(rp->BitMap) > 8))
620 D(bug("write_pixels_8: can't work on hicolor/truecolor screen without LUT"));
621 return 0;
623 #endif
626 gc = GetDriverData(rp, GfxBase);
627 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
629 wp8rd.modulo = modulo;
630 wp8rd.array = array;
631 wp8rd.pixlut = pixlut;
633 rr.MinX = xstart;
634 rr.MinY = ystart;
635 rr.MaxX = xstop;
636 rr.MaxY = ystop;
638 return do_render_with_gc(rp, NULL, &rr, wp8_render, &wp8rd, gc, do_update, FALSE, GfxBase);
641 /****************************************************************************************/
643 struct wtp8_render_data
645 UBYTE *array;
646 ULONG modulo;
647 HIDDT_PixelLUT *pixlut;
648 UBYTE transparent;
651 static ULONG wtp8_render(APTR wtp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
652 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
654 struct wtp8_render_data *wtp8rd = wtp8r_data;
655 WORD width = rect->MaxX - rect->MinX + 1;
656 WORD height = rect->MaxY - rect->MinY + 1;
658 HIDD_BM_PutTranspImageLUT(dstbm_obj, dst_gc,
659 wtp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wtp8rd->modulo), wtp8rd->modulo,
660 rect->MinX, rect->MinY,width, height, wtp8rd->pixlut, wtp8rd->transparent);
662 return width * height;
664 /****************************************************************************************/
666 LONG write_transp_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
667 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
668 HIDDT_PixelLUT *pixlut, UBYTE transparent,
669 BOOL do_update, struct GfxBase *GfxBase)
671 struct wtp8_render_data wtp8rd;
672 struct Rectangle rr;
673 OOP_Object *gc;
675 gc = GetDriverData(rp, GfxBase);
676 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
678 wtp8rd.modulo = modulo;
679 wtp8rd.array = array;
680 wtp8rd.pixlut = pixlut;
681 wtp8rd.transparent = transparent;
683 rr.MinX = xstart;
684 rr.MinY = ystart;
685 rr.MaxX = xstop;
686 rr.MaxY = ystop;
688 return do_render_with_gc(rp, NULL, &rr, wtp8_render, &wtp8rd, gc, do_update, FALSE, GfxBase);
691 /****************************************************************************************/
694 ** General functions for moving blocks of data to or from HIDDs, be it pixelarrays
695 ** or bitmaps. They use a callback-function to get data from amiga/put data to amiga
696 ** bitmaps/pixelarrays
699 /****************************************************************************************/
701 /****************************************************************************************/
703 #define ENABLE_PROFILING 0
704 #define USE_OLD_MoveRaster 0
706 #define rdtscll(val) \
707 __asm__ __volatile__("rdtsc" : "=A" (val))
709 #if ENABLE_PROFILING && defined(__i386__)
712 #define AROS_BEGIN_PROFILING(context) \
714 unsigned long long _time1, _time2; \
715 char *_text = #context; \
716 rdtscll(_time1); \
719 #define AROS_END_PROFILING \
721 rdtscll(_time2); \
722 kprintf("%s: Ticks count: %u\n", _text, (unsigned long)(_time2 - _time1)); \
725 #else
727 #define AROS_BEGIN_PROFILING(context)
728 #define AROS_END_PROFILING
730 #endif
732 BOOL MoveRaster (struct RastPort * rp, WORD dx, WORD dy, WORD x1, WORD y1,
733 WORD x2, WORD y2, BOOL UpdateDamageList, struct GfxBase * GfxBase)
735 struct Layer *L = rp->Layer;
736 struct Rectangle ScrollRect;
737 struct Rectangle Rect;
739 if (0 == dx && 0 == dy)
740 return TRUE;
742 ScrollRect.MinX = x1;
743 ScrollRect.MinY = y1;
744 ScrollRect.MaxX = x2;
745 ScrollRect.MaxY = y2;
747 if (!L)
749 Rect = ScrollRect;
750 TranslateRect(&Rect, -dx, -dy);
751 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
753 BltBitMap(rp->BitMap,
754 Rect.MinX + dx,
755 Rect.MinY + dy,
756 rp->BitMap,
757 Rect.MinX,
758 Rect.MinY,
759 Rect.MaxX - Rect.MinX + 1,
760 Rect.MaxY - Rect.MinY + 1,
761 0xc0, /* copy */
762 0xff,
763 NULL );
766 else
768 struct ClipRect *SrcCR;
770 LockLayerRom(L);
772 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
774 /* Scroll the old damagelist within the scroll area */
775 ScrollRegion(L->DamageList, &ScrollRect, -dx, -dy);
778 /* The scrolling area is relative to the Layer, so make it relative to the screen */
779 TranslateRect(&ScrollRect, MinX(L), MinY(L));
781 /* The damage list will be formed by the now hidden layer's parts that will become visible due
782 to the scrolling procedure, thus we procede this way:
784 1) Calculate the invisible region out of the visible one, subtracting it from the
785 scrolling area
787 2) Scroll the invisible region by (-dx, -dy) and then subtract from it the not scrolled equivalent
789 The regions that we obtain after (2) is the new damage list
792 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
794 Rect = ScrollRect;
796 TranslateRect(&Rect, dx, dy);
798 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
800 struct Region *Damage = NewRegion();
802 if (Damage)
804 #if 1
805 BOOL res = OrRectRegion(Damage, &ScrollRect);
806 #else
807 BOOL res = OrRectRegion(Damage, &Rect);
808 #endif
809 if (!res)
811 DisposeRegion(Damage);
812 Damage = NULL;
816 if (Damage)
820 ClearRegionRegion(L->VisibleRegion, Damage)
822 Damage->RegionRectangle
825 struct Region Tmp;
827 We play sort of dirty here, by making assumptions about the internals of the
828 Region structure and the region handling functions, but we are allowed to do that,
829 aren't we? ;-)
832 Tmp = *Damage;
834 TranslateRect(Bounds(Damage), -dx, -dy);
838 ClearRegionRegion(&Tmp, Damage)
840 Damage->RegionRectangle
843 #if 1
844 AndRectRegion(Damage, &ScrollRect);
845 if (Damage->RegionRectangle)
846 #else
847 #endif
849 /* Join the new damage list with the old one */
850 TranslateRect(Bounds(Damage), -MinX(L), -MinY(L));
851 OrRegionRegion(Damage, L->DamageList);
853 L->Flags |= LAYERREFRESH;
858 DisposeRegion(Damage);
863 AROS_BEGIN_PROFILING(SortLayerCR)
865 if (LayersBase)
866 SortLayerCR(L, dx, dy);
868 AROS_END_PROFILING
870 AROS_BEGIN_PROFILING(Blitting loop)
872 #if USE_OLDMoveRaster
875 struct ClipRect *LastHiddenCR;
877 for (LastHiddenCR = NULL, SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
879 SrcCR->_p1 = LastHiddenCR;
881 if (SrcCR->lobs)
882 LastHiddenCR = SrcCR;
887 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
889 int cando = 0;
891 if (SrcCR->lobs && (L->Flags & LAYERSIMPLE))
893 continue;
896 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
898 TranslateRect(&Rect, -dx, -dy);
900 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
901 cando = 1;
904 if (cando)
906 /* Rect.Min(X|Y) are the coordinates to wich the rectangle has to be moved
907 Rect.Max(X|Y) - Rect.Max(X|Y) - 1 are the dimensions of this rectangle */
908 if (!SrcCR->_p1 && !SrcCR->lobs)
910 /* there are no hidden/obscured rectangles this recrtangle has to deal with*/
911 BltBitMap
913 rp->BitMap,
914 Rect.MinX + dx,
915 Rect.MinY + dy,
916 rp->BitMap,
917 Rect.MinX,
918 Rect.MinY,
919 Rect.MaxX - Rect.MinX + 1,
920 Rect.MaxY - Rect.MinY + 1,
921 0xc0, /* copy */
922 0xff,
923 NULL
926 else
928 struct BitMap *srcbm;
929 struct RegionRectangle *rr;
930 struct Region *RectRegion = NewRegion();
931 struct Rectangle Tmp;
932 struct ClipRect *HiddCR;
933 WORD corrsrcx, corrsrcy;
934 BOOL dosrcsrc;
936 if (!RectRegion)
937 goto failexit;
939 if (!OrRectRegion(&Rect, RectRegion))
941 DisposeRegion(RectRegion);
942 goto failexit;
945 if (SrcCR->lobs)
947 if (L->Flags & LAYERSUPER)
949 corrsrcx = - MinX(L) - L->Scroll_X;
950 corrsrcy = - MinY(L) - L->Scroll_Y;
952 else
954 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
955 corrsrcy = - MinY(SrcCR);
957 srcbm = SrcCR->BitMap;
959 else
961 corrsrcx = 0;
962 corrsrcy = 0;
963 srcbm = rp->BitMap;
966 for (HiddCR = SrcCR->_p1; HiddCR; HiddCR = HiddCR->_p1)
968 if (_AndRectRect(Bounds(RectRegion), Bounds(HiddCR), &Tmp))
970 if (!(L->Flags & LAYERSIMPLE))
972 WORD corrdstx, corrdsty;
974 if (L->Flags & LAYERSUPER)
976 corrdstx = - MinX(L) - L->Scroll_X;
977 corrdsty = - MinY(L) - L->Scroll_Y;
979 else
981 /* Smart layer */
982 corrdstx = - MinX(HiddCR) + ALIGN_OFFSET(MinX(HiddCR));
983 corrdsty = - MinY(HiddCR);
987 BltBitMap
989 srcbm,
990 Tmp.MinX + corrsrcx + dx,
991 Tmp.MinY + corrsrcy + dy,
992 HiddCR->BitMap,
993 Tmp.MinX + corrdstx,
994 Tmp.MinY + corrdsty,
995 Tmp.MaxX - Tmp.MinX + 1,
996 Tmp.MaxY - Tmp.MinY + 1,
997 0xc0, /* copy */
998 0xff,
999 NULL
1003 if (!ClearRectRegion(RectRegion, &Tmp))
1005 DisposeRegion(RectRegion);
1006 goto failexit;
1011 if ((dosrcsrc = _AndRectRect(Bounds(SrcCR), &Rect, &Tmp)))
1013 if (!ClearRectRegion(RectRegion, &Tmp))
1015 DisposeRegion(RectRegion);
1016 goto failexit;
1020 for (rr = RectRegion->RegionRectangle; rr; rr = rr->Next)
1022 BltBitMap
1024 srcbm,
1025 MinX(rr) + MinX(RectRegion) + corrsrcx + dx,
1026 MinY(rr) + MinY(RectRegion) + corrsrcy + dy,
1027 rp->BitMap,
1028 MinX(rr) + MinX(RectRegion),
1029 MinY(rr) + MinY(RectRegion),
1030 Width(rr),
1031 Height(rr),
1032 0xc0, /* copy */
1033 0xff,
1034 NULL
1038 if (dosrcsrc)
1040 BltBitMap
1042 srcbm,
1043 Tmp.MinX + corrsrcx + dx,
1044 Tmp.MinY + corrsrcy + dy,
1045 srcbm,
1046 Tmp.MinX + corrsrcx,
1047 Tmp.MinY + corrsrcy,
1048 Tmp.MaxX - Tmp.MinX + 1,
1049 Tmp.MaxY - Tmp.MinY + 1,
1050 0xc0, /* copy */
1051 0xff,
1052 NULL
1057 DisposeRegion(RectRegion);
1062 #else
1064 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1066 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
1068 TranslateRect(&Rect, -dx, -dy);
1070 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1072 struct BitMap *srcbm;
1073 struct ClipRect *DstCR;
1074 WORD corrsrcx, corrsrcy;
1075 ULONG area;
1077 if (SrcCR->lobs)
1079 if (L->Flags & LAYERSIMPLE) continue;
1081 if (L->Flags & LAYERSUPER)
1083 corrsrcx = - MinX(L) - L->Scroll_X;
1084 corrsrcy = - MinY(L) - L->Scroll_Y;
1086 else
1088 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
1089 corrsrcy = - MinY(SrcCR);
1091 srcbm = SrcCR->BitMap;
1093 else
1095 corrsrcx = 0;
1096 corrsrcy = 0;
1097 srcbm = rp->BitMap;
1100 area = (Rect.MaxX - Rect.MinX + 1) * (Rect.MaxY - Rect.MinY + 1);
1102 for (DstCR = L->ClipRect ; area && DstCR; DstCR = DstCR->Next)
1104 struct Rectangle Rect2;
1106 if (_AndRectRect(Bounds(DstCR), &Rect, &Rect2))
1108 struct BitMap *dstbm;
1109 WORD corrdstx, corrdsty;
1111 area -= (Rect2.MaxX - Rect2.MinX + 1) * (Rect2.MaxY - Rect2.MinY + 1);
1113 if (DstCR->lobs)
1115 if (L->Flags & LAYERSIMPLE) continue;
1117 if (L->Flags & LAYERSUPER)
1119 corrdstx = - MinX(L) - L->Scroll_X;
1120 corrdsty = - MinY(L) - L->Scroll_Y;
1122 else
1124 corrdstx = - MinX(DstCR) + ALIGN_OFFSET(MinX(DstCR));
1125 corrdsty = - MinY(DstCR);
1127 dstbm = DstCR->BitMap;
1129 else
1131 corrdstx = 0;
1132 corrdsty = 0;
1133 dstbm = rp->BitMap;
1136 BltBitMap
1138 srcbm,
1139 Rect2.MinX + corrsrcx + dx,
1140 Rect2.MinY + corrsrcy + dy,
1141 dstbm,
1142 Rect2.MinX + corrdstx,
1143 Rect2.MinY + corrdsty,
1144 Rect2.MaxX - Rect2.MinX + 1,
1145 Rect2.MaxY - Rect2.MinY + 1,
1146 0xC0,
1147 0xFF,
1148 NULL
1155 #endif
1156 AROS_END_PROFILING
1158 UnlockLayerRom(L);
1161 return TRUE;
1164 /****************************************************************************************/
1166 BOOL GetRPClipRectangleForRect(struct RastPort *rp, struct Rectangle *rect, struct Rectangle *r)
1168 struct gfx_driverdata *dd = ObtainDriverData(rp);
1170 if (dd && dd->dd_ClipRectangleFlags & RPCRF_VALID)
1172 *r = dd->dd_ClipRectangle;
1174 if (dd->dd_ClipRectangleFlags & RPCRF_RELRIGHT)
1176 r->MaxX += rect->MaxX - rect->MinX;
1179 if (dd->dd_ClipRectangleFlags & RPCRF_RELBOTTOM)
1181 r->MaxY += rect->MaxY - rect->MinY;
1184 r->MinX += rect->MinX;
1185 r->MinY += rect->MinY;
1186 r->MaxX += rect->MinX;
1187 r->MaxY += rect->MinY;
1189 return TRUE;
1192 return FALSE;
1195 /****************************************************************************************/
1197 BOOL GetRPClipRectangleForBitMap(struct RastPort *rp, struct BitMap *bm,
1198 struct Rectangle *r, struct GfxBase *GfxBase)
1200 struct Rectangle bm_rect;
1201 BOOL res;
1203 bm_rect.MinX = 0;
1204 bm_rect.MinY = 0;
1205 bm_rect.MaxX = GetBitMapAttr(bm, BMA_WIDTH) - 1;
1206 bm_rect.MaxY = GetBitMapAttr(bm, BMA_HEIGHT) - 1;
1208 res = GetRPClipRectangleForRect(rp, &bm_rect, r);
1210 #if BITMAP_CLIPPING
1211 if (!res)
1214 * Set the rectangle to total bitmap size. This prevents trashing memory
1215 * by hitting unallocated memory in HIDDs. They don't check bitmap bounds.
1217 *r = bm_rect;
1218 res = TRUE;
1220 #endif
1222 return res;