Indentation fix, cleanup.
[AROS.git] / rom / graphics / gfxfuncsupport.c
blob518092b477ca1d6a99e68969c194495b5b0ea75f
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 ((rr->MaxX < rr->MinX) || (rr->MaxY < rr->MinY)) return 0;
112 if (NULL != src)
114 srcx = src->x;
115 srcy = src->y;
116 } else
118 srcx = 0;
119 srcy = 0;
122 if (NULL == L)
124 /* No layer, probably a screen, but may be a user inited bitmap */
125 struct Rectangle torender = *rr;
127 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
128 if (have_rp_cliprectangle && !(_AndRectRect(rr, &rp_clip_rectangle, &torender)))
130 return 0;
133 srcx += (torender.MinX - rr->MinX);
134 srcy += (torender.MinY - rr->MinY);
136 if (get_special_info)
138 RSI(funcdata)->curbm = rp->BitMap;
141 pixwritten = CallRenderFunc(render_func, funcdata, srcx, srcy,
142 bm, gc, &torender, do_update, GfxBase);
144 else
146 struct ClipRect *CR;
147 WORD xrel;
148 WORD yrel;
149 struct Rectangle torender, intersect;
151 LockLayerRom(L);
153 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
155 xrel = L->bounds.MinX;
156 yrel = L->bounds.MinY;
158 torender.MinX = rr->MinX + xrel - L->Scroll_X;
159 torender.MinY = rr->MinY + yrel - L->Scroll_Y;
160 torender.MaxX = rr->MaxX + xrel - L->Scroll_X;
161 torender.MaxY = rr->MaxY + yrel - L->Scroll_Y;
163 CR = L->ClipRect;
165 for (;NULL != CR; CR = CR->Next)
167 D(bug("Cliprect (%d, %d, %d, %d), lobs=%p\n",
168 CR->bounds.MinX, CR->bounds.MinY, CR->bounds.MaxX, CR->bounds.MaxY,
169 CR->lobs));
171 /* Does this cliprect intersect with area to rectfill ? */
172 if (_AndRectRect(&CR->bounds, &torender, &intersect))
174 if (!have_rp_cliprectangle || _AndRectRect(&rp_clip_rectangle, &intersect, &intersect))
176 WORD xoffset, yoffset;
178 xoffset = intersect.MinX - torender.MinX;
179 yoffset = intersect.MinY - torender.MinY;
181 if (NULL == CR->lobs)
183 if (get_special_info)
185 RSI(funcdata)->curbm = bm;
188 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
189 bm, gc, &intersect, do_update, GfxBase);
191 else
193 /* Render into offscreen cliprect bitmap */
194 if (L->Flags & LAYERSIMPLE)
195 continue;
196 else if (L->Flags & LAYERSUPER)
198 D(bug("do_render_func(): Superbitmap not handled yet\n"));
200 else
203 if (get_special_info)
205 RSI(funcdata)->curbm = CR->BitMap;
208 intersect.MinX = intersect.MinX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
209 intersect.MinY = intersect.MinY - CR->bounds.MinY;
210 intersect.MaxX = intersect.MaxX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX);
211 intersect.MaxY = intersect.MaxY - CR->bounds.MinY;
213 pixwritten += CallRenderFunc(render_func, funcdata, srcx + xoffset, srcy + yoffset,
214 CR->BitMap, gc, &intersect, do_update, GfxBase);
217 } /* if (CR->lobs == NULL) */
219 } /* if it also intersects with possible rastport clip rectangle */
221 } /* if (cliprect intersects with area to render into) */
223 } /* for (each cliprect in the layer) */
225 UnlockLayerRom(L);
226 } /* if (rp->Layer) */
228 return pixwritten;
231 /****************************************************************************************/
233 static LONG CallPixelFunc(PIXELFUNC render_func, APTR funcdata, struct BitMap *bm, OOP_Object *gc,
234 WORD x, WORD y, BOOL do_update, struct GfxBase *GfxBase)
236 OOP_Object *bm_obj = OBTAIN_HIDD_BM(bm);
237 LONG retval;
239 if (!bm_obj)
240 return -1;
242 retval = render_func(funcdata, bm_obj, gc, x, y, GfxBase);
244 if (do_update)
245 update_bitmap(bm, bm_obj, x, y, 1, 1, GfxBase);
247 RELEASE_HIDD_BM(bm_obj, bm);
248 return retval;
251 ULONG do_pixel_func(struct RastPort *rp
252 , WORD x, WORD y
253 , PIXELFUNC render_func
254 , APTR funcdata
255 , BOOL do_update
256 , struct GfxBase *GfxBase)
258 struct BitMap *bm = rp->BitMap;
259 struct Layer *L = rp->Layer;
260 OOP_Object *gc;
261 struct Rectangle rp_clip_rectangle;
262 BOOL have_rp_cliprectangle;
263 ULONG retval = -1;
265 gc = GetDriverData(rp, GfxBase);
267 if (NULL == L)
269 have_rp_cliprectangle = GetRPClipRectangleForBitMap(rp, bm, &rp_clip_rectangle, GfxBase);
270 if (have_rp_cliprectangle && !_IsPointInRect(&rp_clip_rectangle, x, y))
272 return -1;
275 #if 0 /* With enabled BITMAP_CLIPPING this will be done automatically */
276 OOP_GetAttr(bm_obj, aHidd_BitMap_Width, &width);
277 OOP_GetAttr(bm_obj, aHidd_BitMap_Height, &height);
279 /* Check whether we it is inside the rastport */
280 if ( x < 0
281 || x >= width
282 || y < 0
283 || y >= height)
285 return -1;
287 #endif
289 /* This is a screen */
290 retval = CallPixelFunc(render_func, funcdata, bm, gc, x, y, do_update, GfxBase);
292 else
294 struct ClipRect *CR;
295 WORD absx, absy;
297 LockLayerRom( L );
299 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
301 CR = L->ClipRect;
303 absx = x + L->bounds.MinX - L->Scroll_X;
304 absy = y + L->bounds.MinY - L->Scroll_Y;
306 for (;NULL != CR; CR = CR->Next)
309 if ( absx >= CR->bounds.MinX
310 && absy >= CR->bounds.MinY
311 && absx <= CR->bounds.MaxX
312 && absy <= CR->bounds.MaxY )
315 if (!have_rp_cliprectangle || _IsPointInRect(&rp_clip_rectangle, absx, absy))
317 if (NULL == CR->lobs)
319 retval = CallPixelFunc(render_func, funcdata, bm, gc,
320 absx, absy, do_update, GfxBase);
322 else
324 /* This is the tricky one: render into offscreen cliprect bitmap */
325 if (L->Flags & LAYERSIMPLE)
327 /* We cannot do anything */
328 retval = 0;
331 else if (L->Flags & LAYERSUPER)
333 D(bug("driver_WriteRGBPixel(): Superbitmap not handled yet\n"));
335 else
337 retval = CallPixelFunc(render_func, funcdata, CR->BitMap, gc,
338 absx - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX),
339 absy - CR->bounds.MinY,
340 do_update, GfxBase);
341 } /* If (SMARTREFRESH cliprect) */
343 } /* if (intersecton inside hidden cliprect) */
345 } /* if point is also inside possible rastport clip rectangle */
347 /* The pixel was found and put inside one of the cliprects, just exit */
348 break;
350 } /* if (cliprect intersects with area we want to draw to) */
352 } /* while (cliprects to examine) */
353 UnlockLayerRom( L );
356 return retval;
359 /****************************************************************************************/
361 ULONG fillrect_render(APTR funcdata, WORD srcx, WORD srcy,
362 OOP_Object *dstbm_obj, OOP_Object *dst_gc,
363 struct Rectangle *rect, struct GfxBase *GfxBase)
365 HIDD_BM_FillRect(dstbm_obj, dst_gc, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY);
367 return (rect->MaxX - rect->MinX + 1) * (rect->MaxY - rect->MinY + 1);
370 /****************************************************************************************/
372 LONG fillrect_pendrmd(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
373 HIDDT_Pixel pix, HIDDT_DrawMode drmd, BOOL do_update, struct GfxBase *GfxBase)
375 OOP_Object *gc;
376 struct Rectangle rr;
378 gc = GetDriverData(rp, GfxBase);
379 GC_FG(gc) = pix;
380 GC_DRMD(gc) = drmd;
382 rr.MinX = x1;
383 rr.MinY = y1;
384 rr.MaxX = x2;
385 rr.MaxY = y2;
387 return do_render_with_gc(rp, NULL, &rr, fillrect_render, NULL, gc, do_update, FALSE, GfxBase);
390 /****************************************************************************************/
392 BOOL int_bltbitmap(struct BitMap *srcBitMap, OOP_Object *srcbm_obj, WORD xSrc, WORD ySrc,
393 struct BitMap *dstBitMap, OOP_Object *dstbm_obj, WORD xDest, WORD yDest,
394 WORD xSize, WORD ySize, ULONG minterm, OOP_Object *gfxhidd, OOP_Object *gc,
395 struct GfxBase *GfxBase)
397 HIDDT_DrawMode drmd;
399 ULONG srcflags = 0;
400 ULONG dstflags = 0;
402 BOOL src_colmap_set = FALSE;
403 BOOL dst_colmap_set = FALSE;
404 BOOL success = TRUE;
405 BOOL colmaps_ok = TRUE;
407 drmd = MINTERM_TO_GCDRMD(minterm);
409 /* We must lock any HIDD_BM_SetColorMap calls */
410 LOCK_BLIT
412 /* Try to get a CLUT for the bitmaps */
413 if (IS_HIDD_BM(srcBitMap))
415 //bug("driver_intbltbitmap: source is hidd bitmap\n");
416 if (NULL != HIDD_BM_COLMAP(srcBitMap))
418 //bug("driver_intbltbitmap: source has colormap\n");
419 srcflags |= FLG_HASCOLMAP;
421 srcflags |= GET_COLMOD_FLAGS(srcBitMap);
423 else
425 //bug("driver_intbltbitmap: source is amiga bitmap\n");
426 /* Amiga BM */
427 srcflags |= FLG_PALETTE;
430 if (IS_HIDD_BM(dstBitMap))
432 //bug("driver_intbltbitmap: dest is hidd bitmap\n");
433 if (NULL != HIDD_BM_COLMAP(dstBitMap))
435 //bug("driver_intbltbitmap: dest has colormap\n");
436 dstflags |= FLG_HASCOLMAP;
438 dstflags |= GET_COLMOD_FLAGS(dstBitMap);
440 else
442 //bug("driver_intbltbitmap: dest is amiga bitmap\n");
443 /* Amiga BM */
444 dstflags |= FLG_PALETTE;
447 if ( (srcflags == FLG_PALETTE || srcflags == FLG_STATICPALETTE))
449 /* palettized with no colmap. Need to get a colmap from dest */
450 if (dstflags == FLG_TRUECOLOR)
453 D(bug("!!! NO WAY GETTING PALETTE FOR src IN BltBitMap\n"));
454 colmaps_ok = FALSE;
455 success = FALSE;
458 else if (dstflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
461 /* Use the dest colmap for src */
462 HIDD_BM_SetColorMap(srcbm_obj, HIDD_BM_COLMAP(dstBitMap));
464 src_colmap_set = TRUE;
467 bug("Colormap:\n");
469 ULONG idx;
470 for (idx = 0; idx < 256; idx ++)
471 bug("[%d]=%d ", idx, HIDD_CM_GetPixel(HIDD_BM_COLMAP(dstBitMap), idx));
477 if ( (dstflags == FLG_PALETTE || dstflags == FLG_STATICPALETTE))
479 /* palettized with no pixtab. Nees to get a pixtab from dest*/
480 if (srcflags == FLG_TRUECOLOR)
482 D(bug("!!! NO WAY GETTING PALETTE FOR dst IN BltBitMap\n"));
483 colmaps_ok = FALSE;
484 success = FALSE;
487 else if (srcflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
490 /* Use the src colmap for dst */
491 HIDD_BM_SetColorMap(dstbm_obj, HIDD_BM_COLMAP(srcBitMap));
493 dst_colmap_set = TRUE;
497 if (colmaps_ok)
499 /* We need special treatment with drawmode Clear and
500 truecolor bitmaps, in order to set it to
501 colormap[0] instead of just 0
503 if ( (drmd == vHidd_GC_DrawMode_Clear)
504 && ( (dstflags & (FLG_TRUECOLOR | FLG_HASCOLMAP)) == (FLG_TRUECOLOR | FLG_HASCOLMAP) ))
507 HIDDT_DrawMode old_drmd;
508 IPTR old_fg;
510 struct TagItem frtags[] =
512 { aHidd_GC_Foreground , 0 },
513 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
514 { TAG_DONE }
517 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
518 OOP_GetAttr(gc, aHidd_GC_Foreground, &old_fg);
520 frtags[0].ti_Data = HIDD_BM_PIXTAB(dstBitMap)[0];
521 frtags[1].ti_Data = vHidd_GC_DrawMode_Copy;
523 OOP_SetAttrs(gc, frtags);
525 HIDD_BM_FillRect(dstbm_obj, gc
526 , xDest, yDest
527 , xDest + xSize - 1
528 , yDest + ySize - 1
531 frtags[0].ti_Data = old_fg;
532 frtags[1].ti_Data = old_drmd;
535 else
537 HIDDT_DrawMode old_drmd;
539 struct TagItem cbtags[] =
541 { aHidd_GC_DrawMode, 0 },
542 { TAG_DONE }
545 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
547 cbtags[0].ti_Data = drmd;
549 OOP_SetAttrs(gc, cbtags);
550 HIDD_Gfx_CopyBox(gfxhidd
551 , srcbm_obj
552 , xSrc, ySrc
553 , dstbm_obj
554 , xDest, yDest
555 , xSize, ySize
556 , gc
559 cbtags[0].ti_Data = drmd;
560 OOP_SetAttrs(gc, cbtags);
563 } /* if (colmaps_ok) */
565 if (src_colmap_set)
566 HIDD_BM_SetColorMap(srcbm_obj, NULL);
568 if (dst_colmap_set)
569 HIDD_BM_SetColorMap(dstbm_obj, NULL);
571 ULOCK_BLIT
573 return success;
577 /****************************************************************************************/
579 struct wp8_render_data
581 UBYTE *array;
582 ULONG modulo;
583 HIDDT_PixelLUT *pixlut;
586 static ULONG wp8_render(APTR wp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
587 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
589 struct wp8_render_data *wp8rd = wp8r_data;
590 WORD width = rect->MaxX - rect->MinX + 1;
591 WORD height = rect->MaxY - rect->MinY + 1;
593 HIDD_BM_PutImageLUT(dstbm_obj, dst_gc,
594 wp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wp8rd->modulo), wp8rd->modulo,
595 rect->MinX, rect->MinY, width, height, wp8rd->pixlut);
597 return width * height;
600 /****************************************************************************************/
602 LONG write_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
603 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
604 HIDDT_PixelLUT *pixlut, BOOL do_update, struct GfxBase *GfxBase)
606 struct wp8_render_data wp8rd;
607 struct Rectangle rr;
608 OOP_Object *gc;
609 HIDDT_PixelLUT bm_lut;
611 /* If we haven't got a LUT, we obtain it from the bitmap */
612 if ((!pixlut) && IS_HIDD_BM(rp->BitMap))
614 bm_lut.entries = AROS_PALETTE_SIZE;
615 bm_lut.pixels = HIDD_BM_PIXTAB(rp->BitMap);
616 pixlut = &bm_lut;
618 #ifdef RTG_SANITY_CHECK
619 if ((!bm_lut.pixels) && (HIDD_BM_REALDEPTH(rp->BitMap) > 8))
621 D(bug("write_pixels_8: can't work on hicolor/truecolor screen without LUT"));
622 return 0;
624 #endif
627 gc = GetDriverData(rp, GfxBase);
628 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
630 wp8rd.modulo = modulo;
631 wp8rd.array = array;
632 wp8rd.pixlut = pixlut;
634 rr.MinX = xstart;
635 rr.MinY = ystart;
636 rr.MaxX = xstop;
637 rr.MaxY = ystop;
639 return do_render_with_gc(rp, NULL, &rr, wp8_render, &wp8rd, gc, do_update, FALSE, GfxBase);
642 /****************************************************************************************/
644 struct wtp8_render_data
646 UBYTE *array;
647 ULONG modulo;
648 HIDDT_PixelLUT *pixlut;
649 UBYTE transparent;
652 static ULONG wtp8_render(APTR wtp8r_data, WORD srcx, WORD srcy, OOP_Object *dstbm_obj,
653 OOP_Object *dst_gc, struct Rectangle *rect, struct GfxBase *GfxBase)
655 struct wtp8_render_data *wtp8rd = wtp8r_data;
656 WORD width = rect->MaxX - rect->MinX + 1;
657 WORD height = rect->MaxY - rect->MinY + 1;
659 HIDD_BM_PutTranspImageLUT(dstbm_obj, dst_gc,
660 wtp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wtp8rd->modulo), wtp8rd->modulo,
661 rect->MinX, rect->MinY,width, height, wtp8rd->pixlut, wtp8rd->transparent);
663 return width * height;
665 /****************************************************************************************/
667 LONG write_transp_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
668 WORD xstart, WORD ystart, WORD xstop, WORD ystop,
669 HIDDT_PixelLUT *pixlut, UBYTE transparent,
670 BOOL do_update, struct GfxBase *GfxBase)
672 struct wtp8_render_data wtp8rd;
673 struct Rectangle rr;
674 OOP_Object *gc;
676 gc = GetDriverData(rp, GfxBase);
677 GC_DRMD(gc) = vHidd_GC_DrawMode_Copy;
679 wtp8rd.modulo = modulo;
680 wtp8rd.array = array;
681 wtp8rd.pixlut = pixlut;
682 wtp8rd.transparent = transparent;
684 rr.MinX = xstart;
685 rr.MinY = ystart;
686 rr.MaxX = xstop;
687 rr.MaxY = ystop;
689 return do_render_with_gc(rp, NULL, &rr, wtp8_render, &wtp8rd, gc, do_update, FALSE, GfxBase);
692 /****************************************************************************************/
695 ** General functions for moving blocks of data to or from HIDDs, be it pixelarrays
696 ** or bitmaps. They use a callback-function to get data from amiga/put data to amiga
697 ** bitmaps/pixelarrays
700 /****************************************************************************************/
702 /****************************************************************************************/
704 #define ENABLE_PROFILING 0
705 #define USE_OLD_MoveRaster 0
707 #define rdtscll(val) \
708 __asm__ __volatile__("rdtsc" : "=A" (val))
710 #if ENABLE_PROFILING && defined(__i386__)
713 #define AROS_BEGIN_PROFILING(context) \
715 unsigned long long _time1, _time2; \
716 char *_text = #context; \
717 rdtscll(_time1); \
720 #define AROS_END_PROFILING \
722 rdtscll(_time2); \
723 kprintf("%s: Ticks count: %u\n", _text, (unsigned long)(_time2 - _time1)); \
726 #else
728 #define AROS_BEGIN_PROFILING(context)
729 #define AROS_END_PROFILING
731 #endif
733 BOOL MoveRaster (struct RastPort * rp, WORD dx, WORD dy, WORD x1, WORD y1,
734 WORD x2, WORD y2, BOOL UpdateDamageList, struct GfxBase * GfxBase)
736 struct Layer *L = rp->Layer;
737 struct Rectangle ScrollRect;
738 struct Rectangle Rect;
740 if (0 == dx && 0 == dy)
741 return TRUE;
743 ScrollRect.MinX = x1;
744 ScrollRect.MinY = y1;
745 ScrollRect.MaxX = x2;
746 ScrollRect.MaxY = y2;
748 if (!L)
750 Rect = ScrollRect;
751 TranslateRect(&Rect, -dx, -dy);
752 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
754 BltBitMap(rp->BitMap,
755 Rect.MinX + dx,
756 Rect.MinY + dy,
757 rp->BitMap,
758 Rect.MinX,
759 Rect.MinY,
760 Rect.MaxX - Rect.MinX + 1,
761 Rect.MaxY - Rect.MinY + 1,
762 0xc0, /* copy */
763 0xff,
764 NULL );
767 else
769 struct ClipRect *SrcCR;
771 LockLayerRom(L);
773 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
775 /* Scroll the old damagelist within the scroll area */
776 ScrollRegion(L->DamageList, &ScrollRect, -dx, -dy);
779 /* The scrolling area is relative to the Layer, so make it relative to the screen */
780 TranslateRect(&ScrollRect, MinX(L), MinY(L));
782 /* The damage list will be formed by the now hidden layer's parts that will become visible due
783 to the scrolling procedure, thus we procede this way:
785 1) Calculate the invisible region out of the visible one, subtracting it from the
786 scrolling area
788 2) Scroll the invisible region by (-dx, -dy) and then subtract from it the not scrolled equivalent
790 The regions that we obtain after (2) is the new damage list
793 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
795 Rect = ScrollRect;
797 TranslateRect(&Rect, dx, dy);
799 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
801 struct Region *Damage = NewRegion();
803 if (Damage)
805 #if 1
806 BOOL res = OrRectRegion(Damage, &ScrollRect);
807 #else
808 BOOL res = OrRectRegion(Damage, &Rect);
809 #endif
810 if (!res)
812 DisposeRegion(Damage);
813 Damage = NULL;
817 if (Damage)
821 ClearRegionRegion(L->VisibleRegion, Damage)
823 Damage->RegionRectangle
826 struct Region Tmp;
828 We play sort of dirty here, by making assumptions about the internals of the
829 Region structure and the region handling functions, but we are allowed to do that,
830 aren't we? ;-)
833 Tmp = *Damage;
835 TranslateRect(Bounds(Damage), -dx, -dy);
839 ClearRegionRegion(&Tmp, Damage)
841 Damage->RegionRectangle
844 #if 1
845 AndRectRegion(Damage, &ScrollRect);
846 if (Damage->RegionRectangle)
847 #else
848 #endif
850 /* Join the new damage list with the old one */
851 TranslateRect(Bounds(Damage), -MinX(L), -MinY(L));
852 OrRegionRegion(Damage, L->DamageList);
854 L->Flags |= LAYERREFRESH;
859 DisposeRegion(Damage);
864 AROS_BEGIN_PROFILING(SortLayerCR)
866 if (LayersBase)
867 SortLayerCR(L, dx, dy);
869 AROS_END_PROFILING
871 AROS_BEGIN_PROFILING(Blitting loop)
873 #if USE_OLDMoveRaster
876 struct ClipRect *LastHiddenCR;
878 for (LastHiddenCR = NULL, SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
880 SrcCR->_p1 = LastHiddenCR;
882 if (SrcCR->lobs)
883 LastHiddenCR = SrcCR;
888 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
890 int cando = 0;
892 if (SrcCR->lobs && (L->Flags & LAYERSIMPLE))
894 continue;
897 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
899 TranslateRect(&Rect, -dx, -dy);
901 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
902 cando = 1;
905 if (cando)
907 /* Rect.Min(X|Y) are the coordinates to wich the rectangle has to be moved
908 Rect.Max(X|Y) - Rect.Max(X|Y) - 1 are the dimensions of this rectangle */
909 if (!SrcCR->_p1 && !SrcCR->lobs)
911 /* there are no hidden/obscured rectangles this recrtangle has to deal with*/
912 BltBitMap
914 rp->BitMap,
915 Rect.MinX + dx,
916 Rect.MinY + dy,
917 rp->BitMap,
918 Rect.MinX,
919 Rect.MinY,
920 Rect.MaxX - Rect.MinX + 1,
921 Rect.MaxY - Rect.MinY + 1,
922 0xc0, /* copy */
923 0xff,
924 NULL
927 else
929 struct BitMap *srcbm;
930 struct RegionRectangle *rr;
931 struct Region *RectRegion = NewRegion();
932 struct Rectangle Tmp;
933 struct ClipRect *HiddCR;
934 WORD corrsrcx, corrsrcy;
935 BOOL dosrcsrc;
937 if (!RectRegion)
938 goto failexit;
940 if (!OrRectRegion(&Rect, RectRegion))
942 DisposeRegion(RectRegion);
943 goto failexit;
946 if (SrcCR->lobs)
948 if (L->Flags & LAYERSUPER)
950 corrsrcx = - MinX(L) - L->Scroll_X;
951 corrsrcy = - MinY(L) - L->Scroll_Y;
953 else
955 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
956 corrsrcy = - MinY(SrcCR);
958 srcbm = SrcCR->BitMap;
960 else
962 corrsrcx = 0;
963 corrsrcy = 0;
964 srcbm = rp->BitMap;
967 for (HiddCR = SrcCR->_p1; HiddCR; HiddCR = HiddCR->_p1)
969 if (_AndRectRect(Bounds(RectRegion), Bounds(HiddCR), &Tmp))
971 if (!(L->Flags & LAYERSIMPLE))
973 WORD corrdstx, corrdsty;
975 if (L->Flags & LAYERSUPER)
977 corrdstx = - MinX(L) - L->Scroll_X;
978 corrdsty = - MinY(L) - L->Scroll_Y;
980 else
982 /* Smart layer */
983 corrdstx = - MinX(HiddCR) + ALIGN_OFFSET(MinX(HiddCR));
984 corrdsty = - MinY(HiddCR);
988 BltBitMap
990 srcbm,
991 Tmp.MinX + corrsrcx + dx,
992 Tmp.MinY + corrsrcy + dy,
993 HiddCR->BitMap,
994 Tmp.MinX + corrdstx,
995 Tmp.MinY + corrdsty,
996 Tmp.MaxX - Tmp.MinX + 1,
997 Tmp.MaxY - Tmp.MinY + 1,
998 0xc0, /* copy */
999 0xff,
1000 NULL
1004 if (!ClearRectRegion(RectRegion, &Tmp))
1006 DisposeRegion(RectRegion);
1007 goto failexit;
1012 if ((dosrcsrc = _AndRectRect(Bounds(SrcCR), &Rect, &Tmp)))
1014 if (!ClearRectRegion(RectRegion, &Tmp))
1016 DisposeRegion(RectRegion);
1017 goto failexit;
1021 for (rr = RectRegion->RegionRectangle; rr; rr = rr->Next)
1023 BltBitMap
1025 srcbm,
1026 MinX(rr) + MinX(RectRegion) + corrsrcx + dx,
1027 MinY(rr) + MinY(RectRegion) + corrsrcy + dy,
1028 rp->BitMap,
1029 MinX(rr) + MinX(RectRegion),
1030 MinY(rr) + MinY(RectRegion),
1031 Width(rr),
1032 Height(rr),
1033 0xc0, /* copy */
1034 0xff,
1035 NULL
1039 if (dosrcsrc)
1041 BltBitMap
1043 srcbm,
1044 Tmp.MinX + corrsrcx + dx,
1045 Tmp.MinY + corrsrcy + dy,
1046 srcbm,
1047 Tmp.MinX + corrsrcx,
1048 Tmp.MinY + corrsrcy,
1049 Tmp.MaxX - Tmp.MinX + 1,
1050 Tmp.MaxY - Tmp.MinY + 1,
1051 0xc0, /* copy */
1052 0xff,
1053 NULL
1058 DisposeRegion(RectRegion);
1063 #else
1065 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1067 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
1069 TranslateRect(&Rect, -dx, -dy);
1071 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1073 struct BitMap *srcbm;
1074 struct ClipRect *DstCR;
1075 WORD corrsrcx, corrsrcy;
1076 ULONG area;
1078 if (SrcCR->lobs)
1080 if (L->Flags & LAYERSIMPLE) continue;
1082 if (L->Flags & LAYERSUPER)
1084 corrsrcx = - MinX(L) - L->Scroll_X;
1085 corrsrcy = - MinY(L) - L->Scroll_Y;
1087 else
1089 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
1090 corrsrcy = - MinY(SrcCR);
1092 srcbm = SrcCR->BitMap;
1094 else
1096 corrsrcx = 0;
1097 corrsrcy = 0;
1098 srcbm = rp->BitMap;
1101 area = (Rect.MaxX - Rect.MinX + 1) * (Rect.MaxY - Rect.MinY + 1);
1103 for (DstCR = L->ClipRect ; area && DstCR; DstCR = DstCR->Next)
1105 struct Rectangle Rect2;
1107 if (_AndRectRect(Bounds(DstCR), &Rect, &Rect2))
1109 struct BitMap *dstbm;
1110 WORD corrdstx, corrdsty;
1112 area -= (Rect2.MaxX - Rect2.MinX + 1) * (Rect2.MaxY - Rect2.MinY + 1);
1114 if (DstCR->lobs)
1116 if (L->Flags & LAYERSIMPLE) continue;
1118 if (L->Flags & LAYERSUPER)
1120 corrdstx = - MinX(L) - L->Scroll_X;
1121 corrdsty = - MinY(L) - L->Scroll_Y;
1123 else
1125 corrdstx = - MinX(DstCR) + ALIGN_OFFSET(MinX(DstCR));
1126 corrdsty = - MinY(DstCR);
1128 dstbm = DstCR->BitMap;
1130 else
1132 corrdstx = 0;
1133 corrdsty = 0;
1134 dstbm = rp->BitMap;
1137 BltBitMap
1139 srcbm,
1140 Rect2.MinX + corrsrcx + dx,
1141 Rect2.MinY + corrsrcy + dy,
1142 dstbm,
1143 Rect2.MinX + corrdstx,
1144 Rect2.MinY + corrdsty,
1145 Rect2.MaxX - Rect2.MinX + 1,
1146 Rect2.MaxY - Rect2.MinY + 1,
1147 0xC0,
1148 0xFF,
1149 NULL
1156 #endif
1157 AROS_END_PROFILING
1159 UnlockLayerRom(L);
1162 return TRUE;
1165 /****************************************************************************************/
1167 BOOL GetRPClipRectangleForRect(struct RastPort *rp, struct Rectangle *rect, struct Rectangle *r)
1169 struct gfx_driverdata *dd = ObtainDriverData(rp);
1171 if (dd && dd->dd_ClipRectangleFlags & RPCRF_VALID)
1173 *r = dd->dd_ClipRectangle;
1175 if (dd->dd_ClipRectangleFlags & RPCRF_RELRIGHT)
1177 r->MaxX += rect->MaxX - rect->MinX;
1180 if (dd->dd_ClipRectangleFlags & RPCRF_RELBOTTOM)
1182 r->MaxY += rect->MaxY - rect->MinY;
1185 r->MinX += rect->MinX;
1186 r->MinY += rect->MinY;
1187 r->MaxX += rect->MinX;
1188 r->MaxY += rect->MinY;
1190 return TRUE;
1193 return FALSE;
1196 /****************************************************************************************/
1198 BOOL GetRPClipRectangleForBitMap(struct RastPort *rp, struct BitMap *bm,
1199 struct Rectangle *r, struct GfxBase *GfxBase)
1201 struct Rectangle bm_rect;
1202 BOOL res;
1204 bm_rect.MinX = 0;
1205 bm_rect.MinY = 0;
1206 bm_rect.MaxX = GetBitMapAttr(bm, BMA_WIDTH) - 1;
1207 bm_rect.MaxY = GetBitMapAttr(bm, BMA_HEIGHT) - 1;
1209 res = GetRPClipRectangleForRect(rp, &bm_rect, r);
1211 #if BITMAP_CLIPPING
1212 if (!res)
1215 * Set the rectangle to total bitmap size. This prevents trashing memory
1216 * by hitting unallocated memory in HIDDs. They don't check bitmap bounds.
1218 *r = bm_rect;
1219 res = TRUE;
1221 #endif
1223 return res;