1 // VirtualDub - Video processing and capture application
2 // Graphics support library
3 // Copyright (C) 1998-2009 Avery Lee
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <vd2/system/memory.h>
23 #include <vd2/system/cpuaccel.h>
24 #include <vd2/system/vdstl.h>
25 #include <vd2/Kasumi/pixmap.h>
26 #include <vd2/Kasumi/pixmaputils.h>
27 #include <vd2/Kasumi/pixmapops.h>
29 using namespace nsVDPixmap
;
32 typedef void (*tpPalettedBlitter
)(void *dst
, ptrdiff_t dstpitch
, const void *src
, ptrdiff_t srcpitch
, vdpixsize w
, vdpixsize h
, const void *pal
);
33 typedef void (*tpChunkyBlitter
)(void *dst
, ptrdiff_t dstpitch
, const void *src
, ptrdiff_t srcpitch
, vdpixsize w
, vdpixsize h
);
34 typedef void (*tpPlanarBlitter
)(const VDPixmap
& dst
, const VDPixmap
& src
, vdpixsize w
, vdpixsize h
);
37 bool VDPixmapBltDirect(const VDPixmap
& dst
, const VDPixmap
& src
, vdpixsize w
, vdpixsize h
);
39 void VDPixmapBltDirectPalettedConversion(const VDPixmap
& dst
, const VDPixmap
& src
, vdpixsize w
, vdpixsize h
, tpPalettedBlitter pBlitter
) {
40 uint8 palbytes
[256 * 3];
61 VDASSERT(src
.palette
);
63 VDPixmap srcpal
= { (void *)src
.palette
, NULL
, palsize
, 1, 0, kPixFormat_XRGB8888
};
64 VDPixmap dstpal
= { palbytes
, NULL
, palsize
, 1, 0, dst
.format
};
66 VDVERIFY(VDPixmapBltDirect(dstpal
, srcpal
, palsize
, 1));
68 pBlitter(dst
.data
, dst
.pitch
, src
.data
, src
.pitch
, w
, h
, palbytes
);
71 tpVDPixBltTable
VDPixmapGetBlitterTable() {
72 #if defined(_WIN32) && defined(_M_IX86)
73 static tpVDPixBltTable pBltTable
;
75 if (CPUGetEnabledExtensions() & CPUF_SUPPORTS_MMX
) {
76 return VDGetPixBltTableX86MMX();
78 return VDGetPixBltTableX86Scalar();
81 static tpVDPixBltTable pBltTable
= VDGetPixBltTableReference();
86 bool VDPixmapBltDirect(const VDPixmap
& dst
, const VDPixmap
& src
, vdpixsize w
, vdpixsize h
) {
87 if ((unsigned)src
.format
>= kPixFormat_Max_Standard
) {
92 if ((unsigned)dst
.format
>= kPixFormat_Max_Standard
) {
97 const VDPixmapFormatInfo
& srcinfo
= VDPixmapGetInfo(src
.format
);
99 if (src
.format
== dst
.format
) {
103 if (srcinfo
.qchunky
) {
104 qw
= (qw
+ srcinfo
.qw
- 1) / srcinfo
.qw
;
105 qh
= -(-h
>> srcinfo
.qhbits
);
108 const int auxw
= -(-w
>> srcinfo
.auxwbits
);
109 const int auxh
= -(-h
>> srcinfo
.auxhbits
);
111 switch(srcinfo
.auxbufs
) {
113 VDMemcpyRect(dst
.data3
, dst
.pitch3
, src
.data3
, src
.pitch3
, srcinfo
.auxsize
* auxw
, auxh
);
115 VDMemcpyRect(dst
.data2
, dst
.pitch2
, src
.data2
, src
.pitch2
, srcinfo
.auxsize
* auxw
, auxh
);
117 VDMemcpyRect(dst
.data
, dst
.pitch
, src
.data
, src
.pitch
, srcinfo
.qsize
* qw
, qh
);
123 VDPixmapBlitterFn pBlitter
= VDPixmapGetBlitterTable()[src
.format
][dst
.format
];
128 pBlitter(dst
, src
, w
, h
);
132 bool VDPixmapIsBltPossible(int dst_format
, int src_format
) {
133 if (src_format
== dst_format
)
136 tpVDPixBltTable
tab(VDPixmapGetBlitterTable());
138 if (tab
[src_format
][dst_format
])
141 const VDPixmapFormatInfo
& srcinfo
= VDPixmapGetInfo(src_format
);
142 const VDPixmapFormatInfo
& dstinfo
= VDPixmapGetInfo(dst_format
);
144 if (srcinfo
.auxbufs
> 0 || dstinfo
.auxbufs
> 0)
145 return false; // fail, planar buffers involved (can't do scanlines independently)
147 return (tab
[src_format
][kPixFormat_YUV444_XVYU
] && tab
[kPixFormat_YUV444_XVYU
][dst_format
])
148 ||(tab
[src_format
][kPixFormat_XRGB8888
] && tab
[kPixFormat_XRGB8888
][dst_format
]);
151 bool VDNOINLINE
VDPixmapBltTwoStage(const VDPixmap
& dst
, const VDPixmap
& src
, vdpixsize w
, vdpixsize h
) {
152 const VDPixmapFormatInfo
& srcinfo
= VDPixmapGetInfo(src
.format
);
153 const VDPixmapFormatInfo
& dstinfo
= VDPixmapGetInfo(dst
.format
);
155 if (srcinfo
.auxbufs
> 0 || dstinfo
.auxbufs
> 0)
156 return false; // fail, planar buffers involved
159 return false; // fail, vertically packed formats involved
162 return false; // fail, paletted formats involved
164 // Allocate a 4xW buffer and try round-tripping through either
166 vdblock
<uint32
> tempBuf
;
168 tpVDPixBltTable
tab(VDPixmapGetBlitterTable());
170 VDPixmap
linesrc(src
);
171 VDPixmap
linedst(dst
);
172 VDPixmap linetmp
= {};
175 linetmp
.data
= alloca(sizeof(uint32
) * w
);
177 tempBuf
.resize(w
+ 1);
178 linetmp
.data
= tempBuf
.data();
181 linetmp
.format
= kPixFormat_YUV444_XVYU
;
185 VDPixmapBlitterFn pb1
= tab
[src
.format
][kPixFormat_YUV444_XVYU
];
186 VDPixmapBlitterFn pb2
= tab
[kPixFormat_YUV444_XVYU
][dst
.format
];
188 pb1
= tab
[src
.format
][kPixFormat_XRGB8888
];
189 pb2
= tab
[kPixFormat_XRGB8888
][dst
.format
];
193 linetmp
.format
= kPixFormat_XRGB8888
;
197 pb1(linetmp
, linesrc
, w
, 1);
198 pb2(linedst
, linetmp
, w
, 1);
199 vdptrstep(linesrc
.data
, linesrc
.pitch
);
200 vdptrstep(linedst
.data
, linedst
.pitch
);
205 bool VDPixmapBltFast(const VDPixmap
& dst
, const VDPixmap
& src
, vdpixsize w
, vdpixsize h
) {
206 if (w
<= 0 || h
<= 0) {
207 VDASSERT((w
|h
) >= 0);
211 if (VDPixmapBltDirect(dst
, src
, w
, h
))
214 // Oro... let's see if we can do a two-stage conversion.
215 return VDPixmapBltTwoStage(dst
, src
, w
, h
);
218 bool VDPixmapBlt(const VDPixmap
& dst
, const VDPixmap
& src
) {
219 vdpixsize w
= std::min
<vdpixsize
>(src
.w
, dst
.w
);
220 vdpixsize h
= std::min
<vdpixsize
>(src
.h
, dst
.h
);
225 return VDPixmapBltFast(dst
, src
, w
, h
);
228 bool VDPixmapBlt(const VDPixmap
& dst
, vdpixpos x1
, vdpixpos y1
, const VDPixmap
& src
, vdpixpos x2
, vdpixpos y2
, vdpixsize w
, vdpixsize h
) {
265 if (w
>=0 && h
>= 0) {
266 VDPixmap
dst2(VDPixmapOffset(dst
, x1
, y1
));
267 VDPixmap
src2(VDPixmapOffset(src
, x2
, y2
));
269 return VDPixmapBltFast(dst2
, src2
, w
, h
);
275 extern bool VDPixmapStretchBltNearest_reference(const VDPixmap
& dst
, sint32 x1
, sint32 y1
, sint32 x2
, sint32 y2
, const VDPixmap
& src
, sint32 u1
, sint32 v1
, sint32 u2
, sint32 v2
);
276 extern bool VDPixmapStretchBltBilinear_reference(const VDPixmap
& dst
, sint32 x1
, sint32 y1
, sint32 x2
, sint32 y2
, const VDPixmap
& src
, sint32 u1
, sint32 v1
, sint32 u2
, sint32 v2
);
278 bool VDPixmapStretchBltNearest(const VDPixmap
& dst
, const VDPixmap
& src
) {
279 return VDPixmapStretchBltNearest(dst
, 0, 0, dst
.w
<<16, dst
.h
<<16, src
, 0, 0, src
.w
<<16, src
.h
<<16);
282 bool VDPixmapStretchBltNearest(const VDPixmap
& dst
, sint32 x1
, sint32 y1
, sint32 x2
, sint32 y2
, const VDPixmap
& src
, sint32 u1
, sint32 v1
, sint32 u2
, sint32 v2
) {
283 return VDPixmapStretchBltNearest_reference(dst
, x1
, y1
, x2
, y2
, src
, u1
, v1
, u2
, v2
);
286 bool VDPixmapStretchBltBilinear(const VDPixmap
& dst
, const VDPixmap
& src
) {
287 return VDPixmapStretchBltBilinear(dst
, 0, 0, dst
.w
<<16, dst
.h
<<16, src
, 0, 0, src
.w
<<16, src
.h
<<16);
290 bool VDPixmapStretchBltBilinear(const VDPixmap
& dst
, sint32 x1
, sint32 y1
, sint32 x2
, sint32 y2
, const VDPixmap
& src
, sint32 u1
, sint32 v1
, sint32 u2
, sint32 v2
) {
291 return VDPixmapStretchBltBilinear_reference(dst
, x1
, y1
, x2
, y2
, src
, u1
, v1
, u2
, v2
);