Call "Avail FLUSH" as part of runtime tests.
[AROS.git] / rom / graphics / gfxfuncsupport.c
blobe760ed61908643186c1347e52458de8b315740b6
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
7 #include <aros/debug.h>
9 #include <cybergraphx/cybergraphics.h>
10 #include <graphics/rpattr.h>
11 #include <proto/layers.h>
12 #include <proto/exec.h>
13 #include <proto/graphics.h>
14 #include <proto/oop.h>
15 #include <clib/macros.h>
17 #include "graphics_intern.h"
18 #include "objcache.h"
19 #include "intregions.h"
20 #include "gfxfuncsupport.h"
21 #include "graphics_driver.h"
23 #define DEBUG_PLANARBM(x) DB2(x)
25 #define LayersBase (struct LayersBase *)(GfxBase->gb_LayersBase)
27 /****************************************************************************************/
29 OOP_Object *get_planarbm_object(struct BitMap *bitmap, struct GfxBase *GfxBase)
31 OOP_Object *pbm_obj;
33 DEBUG_PLANARBM(bug("%s: bitmap=%p\n", __func__, bitmap));
34 pbm_obj = obtain_cache_object(CDD(GfxBase)->planarbm_cache, GfxBase);
36 if (NULL != pbm_obj)
39 DEBUG_PLANARBM(bug("%s: cache object %p, class=%s, instoffset=%d\n"
40 , __func__
41 , pbm_obj
42 , OOP_OCLASS(pbm_obj)->ClassNode.ln_Name
43 , OOP_OCLASS(pbm_obj)->InstOffset
44 ));
46 if (!HIDD_PlanarBM_SetBitMap(pbm_obj, bitmap))
48 DEBUG_PLANARBM(bug("!!! get_planarbm_object: HIDD_PlanarBM_SetBitMap FAILED !!!\n"));
49 release_cache_object(CDD(GfxBase)->planarbm_cache, pbm_obj, GfxBase);
50 pbm_obj = NULL;
54 else
56 DEBUG_PLANARBM(bug("!!! get_planarbm_object: obtain_cache_object FAILED !!!\n"));
59 return pbm_obj;
62 /****************************************************************************************/
64 static ULONG CallRenderFunc(RENDERFUNC render_func, APTR funcdata, WORD srcx, WORD srcy,
65 struct BitMap *bm, OOP_Object *gc, struct Rectangle *rect, BOOL do_update,
66 struct GfxBase *GfxBase)
68 OOP_Object *bm_obj = OBTAIN_HIDD_BM(bm);
69 ULONG pixwritten;
71 if (!bm_obj)
72 return 0;
74 pixwritten = render_func(funcdata, srcx, srcy, bm_obj, gc, rect, GfxBase);
76 if (do_update)
77 update_bitmap(bm, bm_obj, rect->MinX, rect->MinY,
78 rect->MaxX - rect->MinX + 1, rect->MaxY - rect->MinY + 1,
79 GfxBase);
81 RELEASE_HIDD_BM(bm_obj, bm);
82 return pixwritten;
85 ULONG do_render_func(struct RastPort *rp, Point *src, struct Rectangle *rr,
86 RENDERFUNC render_func, APTR funcdata,
87 BOOL do_update, BOOL get_special_info, struct GfxBase *GfxBase)
89 OOP_Object *gc = GetDriverData(rp, GfxBase);
91 return do_render_with_gc(rp, src, rr, render_func, funcdata, gc, do_update, get_special_info, GfxBase);
95 * GetDriverData() resets the GC to RastPort's values.
96 * This is another entry point which avoids that. Use it if you have already set up GC.
98 ULONG do_render_with_gc(struct RastPort *rp, Point *src, struct Rectangle *rr,
99 RENDERFUNC render_func, APTR funcdata, OOP_Object *gc,
100 BOOL do_update, BOOL get_special_info, struct GfxBase *GfxBase)
103 struct BitMap *bm = rp->BitMap;
104 struct Layer *L = rp->Layer;
105 struct Rectangle rp_clip_rectangle;
106 BOOL have_rp_cliprectangle;
107 WORD srcx, srcy;
108 LONG pixwritten = 0;
110 if (NULL != src)
112 srcx = src->x;
113 srcy = src->y;
114 } else
116 srcx = 0;
117 srcy = 0;
120 if (NULL == L)
122 /* No layer, probably a screen, but may be a user inited bitmap */
123 struct Rectangle torender = *rr;
125 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
126 if (have_rp_cliprectangle && !(_AndRectRect(rr, &rp_clip_rectangle, &torender)))
128 return 0;
131 srcx += (torender.MinX - rr->MinX);
132 srcy += (torender.MinY - rr->MinY);
134 if (get_special_info)
136 RSI(funcdata)->curbm = rp->BitMap;
139 pixwritten = CallRenderFunc(render_func, funcdata, srcx, srcy,
140 bm, gc, &torender, do_update, GfxBase);
142 else
144 struct ClipRect *CR;
145 WORD xrel;
146 WORD yrel;
147 struct Rectangle torender, intersect;
149 LockLayerRom(L);
151 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
153 xrel = L->bounds.MinX;
154 yrel = L->bounds.MinY;
156 torender.MinX = rr->MinX + xrel - L->Scroll_X;
157 torender.MinY = rr->MinY + yrel - L->Scroll_Y;
158 torender.MaxX = rr->MaxX + xrel - L->Scroll_X;
159 torender.MaxY = rr->MaxY + yrel - L->Scroll_Y;
161 CR = L->ClipRect;
163 for (;NULL != CR; CR = CR->Next)
165 D(bug("Cliprect (%d, %d, %d, %d), lobs=%p\n",
166 CR->bounds.MinX, CR->bounds.MinY, CR->bounds.MaxX, CR->bounds.MaxY,
167 CR->lobs));
169 /* Does this cliprect intersect with area to rectfill ? */
170 if (_AndRectRect(&CR->bounds, &torender, &intersect))
172 if (!have_rp_cliprectangle || _AndRectRect(&rp_clip_rectangle, &intersect, &intersect))
174 WORD xoffset, yoffset;
176 xoffset = intersect.MinX - torender.MinX;
177 yoffset = intersect.MinY - torender.MinY;
179 if (NULL == CR->lobs)
181 if (get_special_info)
183 RSI(funcdata)->curbm = bm;
186 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
187 bm, gc, &intersect, do_update, GfxBase);
189 else
191 /* Render into offscreen cliprect bitmap */
192 if (L->Flags & LAYERSIMPLE)
193 continue;
194 else if (L->Flags & LAYERSUPER)
196 D(bug("do_render_func(): Superbitmap not handled yet\n"));
198 else
201 if (get_special_info)
203 RSI(funcdata)->curbm = CR->BitMap;
206 intersect.MinX = intersect.MinX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
207 intersect.MinY = intersect.MinY - CR->bounds.MinY;
208 intersect.MaxX = intersect.MaxX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
209 intersect.MaxY = intersect.MaxY - CR->bounds.MinY;
211 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
212 CR->BitMap, gc, &intersect, do_update, GfxBase);
215 } /* if (CR->lobs == NULL) */
217 } /* if it also intersects with possible rastport clip rectangle */
219 } /* if (cliprect intersects with area to render into) */
221 } /* for (each cliprect in the layer) */
223 UnlockLayerRom(L);
224 } /* if (rp->Layer) */
226 return pixwritten;
229 /****************************************************************************************/
231 static LONG CallPixelFunc(PIXELFUNC render_func, APTR funcdata, struct BitMap *bm, OOP_Object *gc,
232 WORD x, WORD y, BOOL do_update, struct GfxBase *GfxBase)
234 OOP_Object *bm_obj = OBTAIN_HIDD_BM(bm);
235 LONG retval;
237 if (!bm_obj)
238 return -1;
240 retval = render_func(funcdata, bm_obj, gc, x, y, GfxBase);
242 if (do_update)
243 update_bitmap(bm, bm_obj, x, y, 1, 1, GfxBase);
245 RELEASE_HIDD_BM(bm_obj, bm);
246 return retval;
249 ULONG do_pixel_func(struct RastPort *rp
250 , WORD x, WORD y
251 , PIXELFUNC render_func
252 , APTR funcdata
253 , BOOL do_update
254 , struct GfxBase *GfxBase)
256 struct BitMap *bm = rp->BitMap;
257 struct Layer *L = rp->Layer;
258 OOP_Object *gc;
259 struct Rectangle rp_clip_rectangle;
260 BOOL have_rp_cliprectangle;
261 ULONG retval = -1;
263 gc = GetDriverData(rp, GfxBase);
265 if (NULL == L)
267 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
268 if (have_rp_cliprectangle && !_IsPointInRect(&rp_clip_rectangle, x, y))
270 return -1;
273 #if 0 /* With enabled BITMAP_CLIPPING this will be done automatically */
274 OOP_GetAttr(bm_obj, aHidd_BitMap_Width, &width);
275 OOP_GetAttr(bm_obj, aHidd_BitMap_Height, &height);
277 /* Check whether we it is inside the rastport */
278 if ( x < 0
279 || x >= width
280 || y < 0
281 || y >= height)
283 return -1;
285 #endif
287 /* This is a screen */
288 retval = CallPixelFunc(render_func, funcdata, bm, gc, x, y, do_update, GfxBase);
290 else
292 struct ClipRect *CR;
293 WORD absx, absy;
295 LockLayerRom( L );
297 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
299 CR = L->ClipRect;
301 absx = x + L->bounds.MinX - L->Scroll_X;
302 absy = y + L->bounds.MinY - L->Scroll_Y;
304 for (;NULL != CR; CR = CR->Next)
307 if ( absx >= CR->bounds.MinX
308 && absy >= CR->bounds.MinY
309 && absx <= CR->bounds.MaxX
310 && absy <= CR->bounds.MaxY )
313 if (!have_rp_cliprectangle || _IsPointInRect(&rp_clip_rectangle, absx, absy))
315 if (NULL == CR->lobs)
317 retval = CallPixelFunc(render_func, funcdata, bm, gc,
318 absx, absy, do_update, GfxBase);
320 else
322 /* This is the tricky one: render into offscreen cliprect bitmap */
323 if (L->Flags & LAYERSIMPLE)
325 /* We cannot do anything */
326 retval = 0;
329 else if (L->Flags & LAYERSUPER)
331 D(bug("driver_WriteRGBPixel(): Superbitmap not handled yet\n"));
333 else
335 retval = CallPixelFunc(render_func, funcdata, CR->BitMap, gc,
336 absx - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX),
337 absy - CR->bounds.MinY,
338 do_update, GfxBase);
339 } /* If (SMARTREFRESH cliprect) */
341 } /* if (intersecton inside hidden cliprect) */
343 } /* if point is also inside possible rastport clip rectangle */
345 /* The pixel was found and put inside one of the cliprects, just exit */
346 break;
348 } /* if (cliprect intersects with area we want to draw to) */
350 } /* while (cliprects to examine) */
351 UnlockLayerRom( L );
354 return retval;
357 /****************************************************************************************/
359 ULONG fillrect_render(APTR funcdata, WORD srcx, WORD srcy,
360 OOP_Object *dstbm_obj, OOP_Object *dst_gc,
361 struct Rectangle *rect, struct GfxBase *GfxBase)
363 HIDD_BM_FillRect(dstbm_obj, dst_gc, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY);
365 return (rect->MaxX - rect->MinX + 1) * (rect->MaxY - rect->MinY + 1);
368 /****************************************************************************************/
370 LONG fillrect_pendrmd(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
371 HIDDT_Pixel pix, HIDDT_DrawMode drmd, BOOL do_update, struct GfxBase *GfxBase)
373 OOP_Object *gc;
374 struct Rectangle rr;
376 gc = GetDriverData(rp, GfxBase);
377 GC_FG(gc) = pix;
378 GC_DRMD(gc) = drmd;
380 rr.MinX = x1;
381 rr.MinY = y1;
382 rr.MaxX = x2;
383 rr.MaxY = y2;
385 return do_render_with_gc(rp, NULL, &rr, fillrect_render, NULL, gc, do_update, FALSE, GfxBase);
388 /****************************************************************************************/
390 BOOL int_bltbitmap(struct BitMap *srcBitMap, OOP_Object *srcbm_obj, WORD xSrc, WORD ySrc,
391 struct BitMap *dstBitMap, OOP_Object *dstbm_obj, WORD xDest, WORD yDest,
392 WORD xSize, WORD ySize, ULONG minterm, OOP_Object *gfxhidd, OOP_Object *gc,
393 struct GfxBase *GfxBase)
395 HIDDT_DrawMode drmd;
397 ULONG srcflags = 0;
398 ULONG dstflags = 0;
400 BOOL src_colmap_set = FALSE;
401 BOOL dst_colmap_set = FALSE;
402 BOOL success = TRUE;
403 BOOL colmaps_ok = TRUE;
405 drmd = MINTERM_TO_GCDRMD(minterm);
407 /* We must lock any HIDD_BM_SetColorMap calls */
408 LOCK_BLIT
410 /* Try to get a CLUT for the bitmaps */
411 if (IS_HIDD_BM(srcBitMap))
413 //bug("driver_intbltbitmap: source is hidd bitmap\n");
414 if (NULL != HIDD_BM_COLMAP(srcBitMap))
416 //bug("driver_intbltbitmap: source has colormap\n");
417 srcflags |= FLG_HASCOLMAP;
419 srcflags |= GET_COLMOD_FLAGS(srcBitMap);
421 else
423 //bug("driver_intbltbitmap: source is amiga bitmap\n");
424 /* Amiga BM */
425 srcflags |= FLG_PALETTE;
428 if (IS_HIDD_BM(dstBitMap))
430 //bug("driver_intbltbitmap: dest is hidd bitmap\n");
431 if (NULL != HIDD_BM_COLMAP(dstBitMap))
433 //bug("driver_intbltbitmap: dest has colormap\n");
434 dstflags |= FLG_HASCOLMAP;
436 dstflags |= GET_COLMOD_FLAGS(dstBitMap);
438 else
440 //bug("driver_intbltbitmap: dest is amiga bitmap\n");
441 /* Amiga BM */
442 dstflags |= FLG_PALETTE;
445 if ( (srcflags == FLG_PALETTE || srcflags == FLG_STATICPALETTE))
447 /* palettized with no colmap. Need to get a colmap from dest */
448 if (dstflags == FLG_TRUECOLOR)
451 D(bug("!!! NO WAY GETTING PALETTE FOR src IN BltBitMap\n"));
452 colmaps_ok = FALSE;
453 success = FALSE;
456 else if (dstflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
459 /* Use the dest colmap for src */
460 HIDD_BM_SetColorMap(srcbm_obj, HIDD_BM_COLMAP(dstBitMap));
462 src_colmap_set = TRUE;
465 bug("Colormap:\n");
467 ULONG idx;
468 for (idx = 0; idx < 256; idx ++)
469 bug("[%d]=%d ", idx, HIDD_CM_GetPixel(HIDD_BM_COLMAP(dstBitMap), idx));
475 if ( (dstflags == FLG_PALETTE || dstflags == FLG_STATICPALETTE))
477 /* palettized with no pixtab. Nees to get a pixtab from dest*/
478 if (srcflags == FLG_TRUECOLOR)
480 D(bug("!!! NO WAY GETTING PALETTE FOR dst IN BltBitMap\n"));
481 colmaps_ok = FALSE;
482 success = FALSE;
485 else if (srcflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
488 /* Use the src colmap for dst */
489 HIDD_BM_SetColorMap(dstbm_obj, HIDD_BM_COLMAP(srcBitMap));
491 dst_colmap_set = TRUE;
495 if (colmaps_ok)
497 /* We need special treatment with drawmode Clear and
498 truecolor bitmaps, in order to set it to
499 colormap[0] instead of just 0
501 if ( (drmd == vHidd_GC_DrawMode_Clear)
502 && ( (dstflags & (FLG_TRUECOLOR | FLG_HASCOLMAP)) == (FLG_TRUECOLOR | FLG_HASCOLMAP) ))
505 HIDDT_DrawMode old_drmd;
506 IPTR old_fg;
508 struct TagItem frtags[] =
510 { aHidd_GC_Foreground , 0 },
511 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
512 { TAG_DONE }
515 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
516 OOP_GetAttr(gc, aHidd_GC_Foreground, &old_fg);
518 frtags[0].ti_Data = HIDD_BM_PIXTAB(dstBitMap)[0];
519 frtags[1].ti_Data = vHidd_GC_DrawMode_Copy;
521 OOP_SetAttrs(gc, frtags);
523 HIDD_BM_FillRect(dstbm_obj, gc
524 , xDest, yDest
525 , xDest + xSize - 1
526 , yDest + ySize - 1
529 frtags[0].ti_Data = old_fg;
530 frtags[1].ti_Data = old_drmd;
533 else
535 HIDDT_DrawMode old_drmd;
537 struct TagItem cbtags[] =
539 { aHidd_GC_DrawMode, 0 },
540 { TAG_DONE }
543 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
545 cbtags[0].ti_Data = drmd;
547 OOP_SetAttrs(gc, cbtags);
548 HIDD_Gfx_CopyBox(gfxhidd
549 , srcbm_obj
550 , xSrc, ySrc
551 , dstbm_obj
552 , xDest, yDest
553 , xSize, ySize
554 , gc
557 cbtags[0].ti_Data = drmd;
558 OOP_SetAttrs(gc, cbtags);
561 } /* if (colmaps_ok) */
563 if (src_colmap_set)
564 HIDD_BM_SetColorMap(srcbm_obj, NULL);
566 if (dst_colmap_set)
567 HIDD_BM_SetColorMap(dstbm_obj, NULL);
569 ULOCK_BLIT
571 return success;
575 /****************************************************************************************/
577 struct wp8_render_data
579 UBYTE *array;
580 ULONG modulo;
581 HIDDT_PixelLUT *pixlut;
584 static ULONG wp8_render(APTR wp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
585 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
587 struct wp8_render_data *wp8rd = wp8r_data;
588 WORD width = rect->MaxX - rect->MinX + 1;
589 WORD height = rect->MaxY - rect->MinY + 1;
591 HIDD_BM_PutImageLUT(dstbm_obj, dst_gc,
592 wp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wp8rd->modulo), wp8rd->modulo,
593 rect->MinX, rect->MinY, width, height, wp8rd->pixlut);
595 return width * height;
598 /****************************************************************************************/
600 LONG write_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
601 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
602 HIDDT_PixelLUT *pixlut, BOOL do_update, struct GfxBase *GfxBase)
604 struct wp8_render_data wp8rd;
605 struct Rectangle rr;
606 OOP_Object *gc;
607 HIDDT_PixelLUT bm_lut;
609 /* If we haven't got a LUT, we obtain it from the bitmap */
610 if ((!pixlut) && IS_HIDD_BM(rp->BitMap))
612 bm_lut.entries = AROS_PALETTE_SIZE;
613 bm_lut.pixels = HIDD_BM_PIXTAB(rp->BitMap);
614 pixlut = &bm_lut;
616 #ifdef RTG_SANITY_CHECK
617 if ((!bm_lut.pixels) && (HIDD_BM_REALDEPTH(rp->BitMap) > 8))
619 D(bug("write_pixels_8: can't work on hicolor/truecolor screen without LUT"));
620 return 0;
622 #endif
625 gc = GetDriverData(rp, GfxBase);
626 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
628 wp8rd.modulo = modulo;
629 wp8rd.array = array;
630 wp8rd.pixlut = pixlut;
632 rr.MinX = xstart;
633 rr.MinY = ystart;
634 rr.MaxX = xstop;
635 rr.MaxY = ystop;
637 return do_render_with_gc(rp, NULL, &rr, wp8_render, &wp8rd, gc, do_update, FALSE, GfxBase);
640 /****************************************************************************************/
642 struct wtp8_render_data
644 UBYTE *array;
645 ULONG modulo;
646 HIDDT_PixelLUT *pixlut;
647 UBYTE transparent;
650 static ULONG wtp8_render(APTR wtp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
651 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
653 struct wtp8_render_data *wtp8rd = wtp8r_data;
654 WORD width = rect->MaxX - rect->MinX + 1;
655 WORD height = rect->MaxY - rect->MinY + 1;
657 HIDD_BM_PutTranspImageLUT(dstbm_obj, dst_gc,
658 wtp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wtp8rd->modulo), wtp8rd->modulo,
659 rect->MinX, rect->MinY,width, height, wtp8rd->pixlut, wtp8rd->transparent);
661 return width * height;
663 /****************************************************************************************/
665 LONG write_transp_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
666 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
667 HIDDT_PixelLUT *pixlut, UBYTE transparent,
668 BOOL do_update, struct GfxBase *GfxBase)
670 struct wtp8_render_data wtp8rd;
671 struct Rectangle rr;
672 OOP_Object *gc;
674 gc = GetDriverData(rp, GfxBase);
675 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
677 wtp8rd.modulo = modulo;
678 wtp8rd.array = array;
679 wtp8rd.pixlut = pixlut;
680 wtp8rd.transparent = transparent;
682 rr.MinX = xstart;
683 rr.MinY = ystart;
684 rr.MaxX = xstop;
685 rr.MaxY = ystop;
687 return do_render_with_gc(rp, NULL, &rr, wtp8_render, &wtp8rd, gc, do_update, FALSE, GfxBase);
690 /****************************************************************************************/
693 ** General functions for moving blocks of data to or from HIDDs, be it pixelarrays
694 ** or bitmaps. They use a callback-function to get data from amiga/put data to amiga
695 ** bitmaps/pixelarrays
698 /****************************************************************************************/
700 /****************************************************************************************/
702 #define ENABLE_PROFILING 0
703 #define USE_OLD_MoveRaster 0
705 #define rdtscll(val) \
706 __asm__ __volatile__("rdtsc" : "=A" (val))
708 #if ENABLE_PROFILING && defined(__i386__)
711 #define AROS_BEGIN_PROFILING(context) \
713 unsigned long long _time1, _time2; \
714 char *_text = #context; \
715 rdtscll(_time1); \
718 #define AROS_END_PROFILING \
720 rdtscll(_time2); \
721 kprintf("%s: Ticks count: %u\n", _text, (unsigned long)(_time2 - _time1)); \
724 #else
726 #define AROS_BEGIN_PROFILING(context)
727 #define AROS_END_PROFILING
729 #endif
731 BOOL MoveRaster (struct RastPort * rp, WORD dx, WORD dy, WORD x1, WORD y1,
732 WORD x2, WORD y2, BOOL UpdateDamageList, struct GfxBase * GfxBase)
734 struct Layer *L = rp->Layer;
735 struct Rectangle ScrollRect;
736 struct Rectangle Rect;
738 if (0 == dx && 0 == dy)
739 return TRUE;
741 ScrollRect.MinX = x1;
742 ScrollRect.MinY = y1;
743 ScrollRect.MaxX = x2;
744 ScrollRect.MaxY = y2;
746 if (!L)
748 Rect = ScrollRect;
749 TranslateRect(&Rect, -dx, -dy);
750 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
752 BltBitMap(rp->BitMap,
753 Rect.MinX + dx,
754 Rect.MinY + dy,
755 rp->BitMap,
756 Rect.MinX,
757 Rect.MinY,
758 Rect.MaxX - Rect.MinX + 1,
759 Rect.MaxY - Rect.MinY + 1,
760 0xc0, /* copy */
761 0xff,
762 NULL );
765 else
767 struct ClipRect *SrcCR;
769 LockLayerRom(L);
771 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
773 /* Scroll the old damagelist within the scroll area */
774 ScrollRegion(L->DamageList, &ScrollRect, -dx, -dy);
777 /* The scrolling area is relative to the Layer, so make it relative to the screen */
778 TranslateRect(&ScrollRect, MinX(L), MinY(L));
780 /* The damage list will be formed by the now hidden layer's parts that will become visible due
781 to the scrolling procedure, thus we procede this way:
783 1) Calculate the invisible region out of the visible one, subtracting it from the
784 scrolling area
786 2) Scroll the invisible region by (-dx, -dy) and then subtract from it the not scrolled equivalent
788 The regions that we obtain after (2) is the new damage list
791 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
793 Rect = ScrollRect;
795 TranslateRect(&Rect, dx, dy);
797 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
799 struct Region *Damage = NewRegion();
801 if (Damage)
803 #if 1
804 BOOL res = OrRectRegion(Damage, &ScrollRect);
805 #else
806 BOOL res = OrRectRegion(Damage, &Rect);
807 #endif
808 if (!res)
810 DisposeRegion(Damage);
811 Damage = NULL;
815 if (Damage)
819 ClearRegionRegion(L->VisibleRegion, Damage)
821 Damage->RegionRectangle
824 struct Region Tmp;
826 We play sort of dirty here, by making assumptions about the internals of the
827 Region structure and the region handling functions, but we are allowed to do that,
828 aren't we? ;-)
831 Tmp = *Damage;
833 TranslateRect(Bounds(Damage), -dx, -dy);
837 ClearRegionRegion(&Tmp, Damage)
839 Damage->RegionRectangle
842 #if 1
843 AndRectRegion(Damage, &ScrollRect);
844 if (Damage->RegionRectangle)
845 #else
846 #endif
848 /* Join the new damage list with the old one */
849 TranslateRect(Bounds(Damage), -MinX(L), -MinY(L));
850 OrRegionRegion(Damage, L->DamageList);
852 L->Flags |= LAYERREFRESH;
857 DisposeRegion(Damage);
862 AROS_BEGIN_PROFILING(SortLayerCR)
864 if (LayersBase)
865 SortLayerCR(L, dx, dy);
867 AROS_END_PROFILING
869 AROS_BEGIN_PROFILING(Blitting loop)
871 #if USE_OLDMoveRaster
874 struct ClipRect *LastHiddenCR;
876 for (LastHiddenCR = NULL, SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
878 SrcCR->_p1 = LastHiddenCR;
880 if (SrcCR->lobs)
881 LastHiddenCR = SrcCR;
886 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
888 int cando = 0;
890 if (SrcCR->lobs && (L->Flags & LAYERSIMPLE))
892 continue;
895 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
897 TranslateRect(&Rect, -dx, -dy);
899 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
900 cando = 1;
903 if (cando)
905 /* Rect.Min(X|Y) are the coordinates to wich the rectangle has to be moved
906 Rect.Max(X|Y) - Rect.Max(X|Y) - 1 are the dimensions of this rectangle */
907 if (!SrcCR->_p1 && !SrcCR->lobs)
909 /* there are no hidden/obscured rectangles this recrtangle has to deal with*/
910 BltBitMap
912 rp->BitMap,
913 Rect.MinX + dx,
914 Rect.MinY + dy,
915 rp->BitMap,
916 Rect.MinX,
917 Rect.MinY,
918 Rect.MaxX - Rect.MinX + 1,
919 Rect.MaxY - Rect.MinY + 1,
920 0xc0, /* copy */
921 0xff,
922 NULL
925 else
927 struct BitMap *srcbm;
928 struct RegionRectangle *rr;
929 struct Region *RectRegion = NewRegion();
930 struct Rectangle Tmp;
931 struct ClipRect *HiddCR;
932 WORD corrsrcx, corrsrcy;
933 BOOL dosrcsrc;
935 if (!RectRegion)
936 goto failexit;
938 if (!OrRectRegion(&Rect, RectRegion))
940 DisposeRegion(RectRegion);
941 goto failexit;
944 if (SrcCR->lobs)
946 if (L->Flags & LAYERSUPER)
948 corrsrcx = - MinX(L) - L->Scroll_X;
949 corrsrcy = - MinY(L) - L->Scroll_Y;
951 else
953 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
954 corrsrcy = - MinY(SrcCR);
956 srcbm = SrcCR->BitMap;
958 else
960 corrsrcx = 0;
961 corrsrcy = 0;
962 srcbm = rp->BitMap;
965 for (HiddCR = SrcCR->_p1; HiddCR; HiddCR = HiddCR->_p1)
967 if (_AndRectRect(Bounds(RectRegion), Bounds(HiddCR), &Tmp))
969 if (!(L->Flags & LAYERSIMPLE))
971 WORD corrdstx, corrdsty;
973 if (L->Flags & LAYERSUPER)
975 corrdstx = - MinX(L) - L->Scroll_X;
976 corrdsty = - MinY(L) - L->Scroll_Y;
978 else
980 /* Smart layer */
981 corrdstx = - MinX(HiddCR) + ALIGN_OFFSET(MinX(HiddCR));
982 corrdsty = - MinY(HiddCR);
986 BltBitMap
988 srcbm,
989 Tmp.MinX + corrsrcx + dx,
990 Tmp.MinY + corrsrcy + dy,
991 HiddCR->BitMap,
992 Tmp.MinX + corrdstx,
993 Tmp.MinY + corrdsty,
994 Tmp.MaxX - Tmp.MinX + 1,
995 Tmp.MaxY - Tmp.MinY + 1,
996 0xc0, /* copy */
997 0xff,
998 NULL
1002 if (!ClearRectRegion(RectRegion, &Tmp))
1004 DisposeRegion(RectRegion);
1005 goto failexit;
1010 if ((dosrcsrc = _AndRectRect(Bounds(SrcCR), &Rect, &Tmp)))
1012 if (!ClearRectRegion(RectRegion, &Tmp))
1014 DisposeRegion(RectRegion);
1015 goto failexit;
1019 for (rr = RectRegion->RegionRectangle; rr; rr = rr->Next)
1021 BltBitMap
1023 srcbm,
1024 MinX(rr) + MinX(RectRegion) + corrsrcx + dx,
1025 MinY(rr) + MinY(RectRegion) + corrsrcy + dy,
1026 rp->BitMap,
1027 MinX(rr) + MinX(RectRegion),
1028 MinY(rr) + MinY(RectRegion),
1029 Width(rr),
1030 Height(rr),
1031 0xc0, /* copy */
1032 0xff,
1033 NULL
1037 if (dosrcsrc)
1039 BltBitMap
1041 srcbm,
1042 Tmp.MinX + corrsrcx + dx,
1043 Tmp.MinY + corrsrcy + dy,
1044 srcbm,
1045 Tmp.MinX + corrsrcx,
1046 Tmp.MinY + corrsrcy,
1047 Tmp.MaxX - Tmp.MinX + 1,
1048 Tmp.MaxY - Tmp.MinY + 1,
1049 0xc0, /* copy */
1050 0xff,
1051 NULL
1056 DisposeRegion(RectRegion);
1061 #else
1063 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1065 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
1067 TranslateRect(&Rect, -dx, -dy);
1069 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1071 struct BitMap *srcbm;
1072 struct ClipRect *DstCR;
1073 WORD corrsrcx, corrsrcy;
1074 ULONG area;
1076 if (SrcCR->lobs)
1078 if (L->Flags & LAYERSIMPLE) continue;
1080 if (L->Flags & LAYERSUPER)
1082 corrsrcx = - MinX(L) - L->Scroll_X;
1083 corrsrcy = - MinY(L) - L->Scroll_Y;
1085 else
1087 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
1088 corrsrcy = - MinY(SrcCR);
1090 srcbm = SrcCR->BitMap;
1092 else
1094 corrsrcx = 0;
1095 corrsrcy = 0;
1096 srcbm = rp->BitMap;
1099 area = (Rect.MaxX - Rect.MinX + 1) * (Rect.MaxY - Rect.MinY + 1);
1101 for (DstCR = L->ClipRect ; area && DstCR; DstCR = DstCR->Next)
1103 struct Rectangle Rect2;
1105 if (_AndRectRect(Bounds(DstCR), &Rect, &Rect2))
1107 struct BitMap *dstbm;
1108 WORD corrdstx, corrdsty;
1110 area -= (Rect2.MaxX - Rect2.MinX + 1) * (Rect2.MaxY - Rect2.MinY + 1);
1112 if (DstCR->lobs)
1114 if (L->Flags & LAYERSIMPLE) continue;
1116 if (L->Flags & LAYERSUPER)
1118 corrdstx = - MinX(L) - L->Scroll_X;
1119 corrdsty = - MinY(L) - L->Scroll_Y;
1121 else
1123 corrdstx = - MinX(DstCR) + ALIGN_OFFSET(MinX(DstCR));
1124 corrdsty = - MinY(DstCR);
1126 dstbm = DstCR->BitMap;
1128 else
1130 corrdstx = 0;
1131 corrdsty = 0;
1132 dstbm = rp->BitMap;
1135 BltBitMap
1137 srcbm,
1138 Rect2.MinX + corrsrcx + dx,
1139 Rect2.MinY + corrsrcy + dy,
1140 dstbm,
1141 Rect2.MinX + corrdstx,
1142 Rect2.MinY + corrdsty,
1143 Rect2.MaxX - Rect2.MinX + 1,
1144 Rect2.MaxY - Rect2.MinY + 1,
1145 0xC0,
1146 0xFF,
1147 NULL
1154 #endif
1155 AROS_END_PROFILING
1157 UnlockLayerRom(L);
1160 return TRUE;
1163 /****************************************************************************************/
1165 BOOL GetRPClipRectangleForRect(struct RastPort *rp, struct Rectangle *rect, struct Rectangle *r)
1167 struct gfx_driverdata *dd = ObtainDriverData(rp);
1169 if (dd && dd->dd_ClipRectangleFlags & RPCRF_VALID)
1171 *r = dd->dd_ClipRectangle;
1173 if (dd->dd_ClipRectangleFlags & RPCRF_RELRIGHT)
1175 r->MaxX += rect->MaxX - rect->MinX;
1178 if (dd->dd_ClipRectangleFlags & RPCRF_RELBOTTOM)
1180 r->MaxY += rect->MaxY - rect->MinY;
1183 r->MinX += rect->MinX;
1184 r->MinY += rect->MinY;
1185 r->MaxX += rect->MinX;
1186 r->MaxY += rect->MinY;
1188 return TRUE;
1191 return FALSE;
1194 /****************************************************************************************/
1196 BOOL GetRPClipRectangleForBitMap(struct RastPort *rp, struct BitMap *bm,
1197 struct Rectangle *r, struct GfxBase *GfxBase)
1199 struct Rectangle bm_rect;
1200 BOOL res;
1202 bm_rect.MinX = 0;
1203 bm_rect.MinY = 0;
1204 bm_rect.MaxX = GetBitMapAttr(bm, BMA_WIDTH) - 1;
1205 bm_rect.MaxY = GetBitMapAttr(bm, BMA_HEIGHT) - 1;
1207 res = GetRPClipRectangleForRect(rp, &bm_rect, r);
1209 #if BITMAP_CLIPPING
1210 if (!res)
1213 * Set the rectangle to total bitmap size. This prevents trashing memory
1214 * by hitting unallocated memory in HIDDs. They don't check bitmap bounds.
1216 *r = bm_rect;
1217 res = TRUE;
1219 #endif
1221 return res;