Fix the workaround for optimization register spill issues on newer m68k GCC toolchain...
[AROS.git] / workbench / libs / cgfx / scalepixelarray.c
blobbe8078f91d0ff45be27381f1691ad9215db07a32
1 /*
2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <hidd/gfx.h>
11 #include <proto/cybergraphics.h>
13 #include "cybergraphics_intern.h"
14 #include "gfxfuncsupport.h"
16 struct render_data
18 OOP_Object *srcbm_obj;
19 OOP_Object *gfx_hidd;
22 static ULONG RenderHook(struct render_data *data, LONG srcx, LONG srcy,
23 OOP_Object *dstbm_obj, OOP_Object *dst_gc, struct Rectangle *rect,
24 struct GfxBase *GfxBase);
26 /* Work around an m68k GCC issue, with AROS_LH10 macros.
28 * Due to the AROS_LH10() macro using so many data registers,
29 * we get a register spill during certain optimization levels.
31 * This 'hack' thunks the register call to a stack call, and passes
32 * the bounds using an address register, so that optimization has more
33 * data registers to play with.
35 * NB: It must have global scope (not 'static') so that it doesn't fold
36 * into the regcall routine. On non-regcall systems, this will, at worst,
37 * convert to a 'JMP internal_ScalePixelArray' with no stack manipulation.
39 LONG internal_ScalePixelArray(APTR srcRect, UWORD SrcW, UWORD SrcH, UWORD SrcMod, struct RastPort *RastPort, struct Rectangle *DstBounds, UBYTE SrcFormat, struct Library *CyberGfxBase);
41 /*****************************************************************************
43 NAME */
44 #include <proto/cybergraphics.h>
46 AROS_LH10(LONG, ScalePixelArray,
48 /* SYNOPSIS */
49 AROS_LHA(APTR , srcRect, A0),
50 AROS_LHA(UWORD , SrcW, D0),
51 AROS_LHA(UWORD , SrcH, D1),
52 AROS_LHA(UWORD , SrcMod, D2),
53 AROS_LHA(struct RastPort *, RastPort, A1),
54 AROS_LHA(UWORD , DestX, D3),
55 AROS_LHA(UWORD , DestY, D4),
56 AROS_LHA(UWORD , DestW, D5),
57 AROS_LHA(UWORD , DestH, D6),
58 AROS_LHA(UBYTE , SrcFormat, D7),
60 /* LOCATION */
61 struct Library *, CyberGfxBase, 15, Cybergraphics)
63 /* FUNCTION
64 Fills all or part of a RastPort with a rectangular block of raw pixel
65 values. The source pixels are scaled to fit the destination area, i.e.
66 some pixels may be duplicated or dropped according to the need to
67 stretch or compress the source block.
69 INPUTS
70 srcRect - pointer to the pixel values.
71 SrcW, SrcH - width and height of the source rectangle (in pixels).
72 SrcMod - the number of bytes in each row of the source rectangle.
73 RastPort - the RastPort to write to.
74 DestX, DestY - top-lefthand corner of portion of destination RastPort
75 to write to (in pixels).
76 DestW, DestH - size of the destination rectangle (in pixels).
77 SrcFormat - the format of the source pixels. See WritePixelArray for
78 possible values.
80 RESULT
81 count - the number of pixels written to.
83 NOTES
85 EXAMPLE
87 BUGS
89 SEE ALSO
90 WritePixelArray()
92 INTERNALS
94 *****************************************************************************/
96 AROS_LIBFUNC_INIT
98 struct Rectangle DestBounds;
100 DestBounds.MinX = DestX;
101 DestBounds.MinY = DestY;
102 DestBounds.MaxX = DestW;
103 DestBounds.MaxY = DestH;
105 return internal_ScalePixelArray(srcRect, SrcW, SrcH, SrcMod, RastPort, &DestBounds, SrcFormat, CyberGfxBase);
107 AROS_LIBFUNC_EXIT
110 LONG internal_ScalePixelArray(APTR srcRect, UWORD SrcW, UWORD SrcH, UWORD SrcMod, struct RastPort *RastPort, struct Rectangle *DstBounds, UBYTE SrcFormat, struct Library *CyberGfxBase)
112 ULONG result = 0;
113 struct render_data data;
114 struct Rectangle rr;
115 OOP_Object *gfx_hidd, *tempbm_obj, *tempbm2_obj, *gc;
116 struct BitScaleArgs scale_args = {0};
117 struct TagItem bm_tags[] =
119 {aHidd_BitMap_GfxHidd, 0},
120 {aHidd_BitMap_Width, SrcW},
121 {aHidd_BitMap_Height, SrcH},
122 {aHidd_BitMap_StdPixFmt, 0},
123 {TAG_END, 0}
125 struct TagItem gc_tags[] =
127 {aHidd_GC_DrawMode, vHidd_GC_DrawMode_Copy},
128 {TAG_DONE, 0UL}
131 D(bug("ScalePixelArray(%p, %d, %d, %d, %p, %d, %d, %d, %d, %d)\n",
132 srcRect, SrcW, SrcH, SrcMod, RastPort, DstBounds->MinX, DstBounds->MinY, DstBounds->MaxX, DstBounds->MaxY,
133 SrcFormat));
135 if (SrcW == 0 || SrcH == 0 || DstBounds->MaxX == 0 || DstBounds->MaxY == 0)
136 return 0;
138 /* This is AROS Cybergraphx - We only work wih Gfx Hidd bitmaps */
140 if (!IS_HIDD_BM(RastPort->BitMap))
142 D(bug("!!!!! Trying to use CGFX call on non-hidd bitmap in ScalePixelArray() !!!\n"));
143 return 0;
146 /* Query the bitmaps Gfx Hidd, and create a suitable GC Object (graphics context) */
148 OOP_GetAttr(HIDD_BM_OBJ(RastPort->BitMap), aHidd_BitMap_GfxHidd,
149 (IPTR *)&gfx_hidd);
150 gc = HIDD_Gfx_CreateObject(gfx_hidd, GetCGFXBase(CyberGfxBase)->basegc, gc_tags);
151 if (gc)
153 /* Create two temporary bitmap objects: one the size of the source area
154 and another the size of the destination area */
156 bm_tags[0].ti_Data = (IPTR)gfx_hidd;
157 bm_tags[3].ti_Data = GetHIDDRectFmt(SrcFormat, RastPort, CyberGfxBase);
158 tempbm_obj = HIDD_Gfx_CreateObject(gfx_hidd, GetCGFXBase(CyberGfxBase)->basebm, bm_tags);
159 if (tempbm_obj)
161 bm_tags[1].ti_Data = DstBounds->MaxX;
162 bm_tags[2].ti_Data = DstBounds->MaxY;
163 #if 0
164 // FIXME: This doesn't work (X11 and VESA). Should it?
165 bm_tags[3].ti_Tag = aHidd_BitMap_Friend;
166 bm_tags[3].ti_Data = (IPTR)HIDD_BM_OBJ(RastPort->BitMap);
167 #endif
168 tempbm2_obj = HIDD_Gfx_CreateObject(gfx_hidd, GetCGFXBase(CyberGfxBase)->basebm, bm_tags);
169 if (tempbm2_obj)
171 /* Copy the source array to its temporary bitmap object */
173 HIDD_BM_PutImage(tempbm_obj, gc, srcRect, SrcMod, 0, 0, SrcW, SrcH,
174 vHidd_StdPixFmt_Native);
176 /* Scale temporary source bitmap on to temporary destination bitmap */
178 scale_args.bsa_SrcWidth = SrcW;
179 scale_args.bsa_SrcHeight = SrcH;
180 scale_args.bsa_DestWidth = DstBounds->MaxX;
181 scale_args.bsa_DestHeight = DstBounds->MaxY;
182 HIDD_BM_BitMapScale(tempbm2_obj, tempbm_obj, tempbm2_obj, &scale_args,
183 gc);
185 /* Render temporary destination bitmap to destination bitmap */
187 data.srcbm_obj = tempbm2_obj;
188 data.gfx_hidd = gfx_hidd;
189 rr.MinX = DstBounds->MinX;
190 rr.MinY = DstBounds->MinY;
191 rr.MaxX = DstBounds->MinX + DstBounds->MaxX - 1;
192 rr.MaxY = DstBounds->MinY + DstBounds->MaxY - 1;
193 result = DoRenderFunc(RastPort, NULL, &rr, RenderHook, &data, TRUE);
196 * Discard temporary resources ...
199 OOP_DisposeObject(tempbm2_obj);
201 OOP_DisposeObject(tempbm_obj);
203 OOP_DisposeObject(gc);
206 return result;
207 } /* ScalePixelArray */
209 static ULONG RenderHook(struct render_data *data, LONG srcx, LONG srcy,
210 OOP_Object *dstbm_obj, OOP_Object *dst_gc, struct Rectangle *rect,
211 struct GfxBase *GfxBase)
213 ULONG width = rect->MaxX - rect->MinX + 1;
214 ULONG height = rect->MaxY - rect->MinY + 1;
216 HIDD_Gfx_CopyBox(data->gfx_hidd, data->srcbm_obj, srcx, srcy, dstbm_obj,
217 rect->MinX, rect->MinY, width, height, dst_gc);
219 return width * height;