SDL  2.0
SDL_yuv_sw.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 /* This is the software implementation of the YUV texture support */
24 
25 #if SDL_HAVE_YUV
26 
27 #include "SDL_assert.h"
28 
29 #include "SDL_yuv_sw_c.h"
30 
31 
34 {
35  SDL_SW_YUVTexture *swdata;
36 
37  switch (format) {
45  break;
46  default:
47  SDL_SetError("Unsupported YUV format");
48  return NULL;
49  }
50 
51  swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
52  if (!swdata) {
54  return NULL;
55  }
56 
57  swdata->format = format;
59  swdata->w = w;
60  swdata->h = h;
61  {
62  const int sz_plane = w * h;
63  const int sz_plane_chroma = ((w + 1) / 2) * ((h + 1) / 2);
64  const int sz_plane_packed = ((w + 1) / 2) * h;
65  int dst_size = 0;
66  switch(format)
67  {
68  case SDL_PIXELFORMAT_YV12: /**< Planar mode: Y + V + U (3 planes) */
69  case SDL_PIXELFORMAT_IYUV: /**< Planar mode: Y + U + V (3 planes) */
70  dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
71  break;
72 
73  case SDL_PIXELFORMAT_YUY2: /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
74  case SDL_PIXELFORMAT_UYVY: /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
75  case SDL_PIXELFORMAT_YVYU: /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
76  dst_size = 4 * sz_plane_packed;
77  break;
78 
79  case SDL_PIXELFORMAT_NV12: /**< Planar mode: Y + U/V interleaved (2 planes) */
80  case SDL_PIXELFORMAT_NV21: /**< Planar mode: Y + V/U interleaved (2 planes) */
81  dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
82  break;
83 
84  default:
85  SDL_assert(0 && "We should never get here (caught above)");
86  break;
87  }
88  swdata->pixels = (Uint8 *) SDL_malloc(dst_size);
89  if (!swdata->pixels) {
92  return NULL;
93  }
94  }
95 
96  /* Find the pitch and offset values for the texture */
97  switch (format) {
100  swdata->pitches[0] = w;
101  swdata->pitches[1] = (swdata->pitches[0] + 1) / 2;
102  swdata->pitches[2] = (swdata->pitches[0] + 1) / 2;
103  swdata->planes[0] = swdata->pixels;
104  swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
105  swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * ((h + 1) / 2);
106  break;
110  swdata->pitches[0] = ((w + 1) / 2) * 4;
111  swdata->planes[0] = swdata->pixels;
112  break;
113 
116  swdata->pitches[0] = w;
117  swdata->pitches[1] = 2 * ((swdata->pitches[0] + 1) / 2);
118  swdata->planes[0] = swdata->pixels;
119  swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
120  break;
121 
122  default:
123  SDL_assert(0 && "We should never get here (caught above)");
124  break;
125  }
126 
127  /* We're all done.. */
128  return (swdata);
129 }
130 
131 int
133  int *pitch)
134 {
135  *pixels = swdata->planes[0];
136  *pitch = swdata->pitches[0];
137  return 0;
138 }
139 
140 int
142  const void *pixels, int pitch)
143 {
144  switch (swdata->format) {
147  if (rect->x == 0 && rect->y == 0 &&
148  rect->w == swdata->w && rect->h == swdata->h) {
149  SDL_memcpy(swdata->pixels, pixels,
150  (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
151  } else {
152  Uint8 *src, *dst;
153  int row;
154  size_t length;
155 
156  /* Copy the Y plane */
157  src = (Uint8 *) pixels;
158  dst = swdata->pixels + rect->y * swdata->w + rect->x;
159  length = rect->w;
160  for (row = 0; row < rect->h; ++row) {
162  src += pitch;
163  dst += swdata->w;
164  }
165 
166  /* Copy the next plane */
167  src = (Uint8 *) pixels + rect->h * pitch;
168  dst = swdata->pixels + swdata->h * swdata->w;
169  dst += rect->y/2 * ((swdata->w + 1) / 2) + rect->x/2;
170  length = (rect->w + 1) / 2;
171  for (row = 0; row < (rect->h + 1)/2; ++row) {
173  src += (pitch + 1)/2;
174  dst += (swdata->w + 1)/2;
175  }
176 
177  /* Copy the next plane */
178  src = (Uint8 *) pixels + rect->h * pitch + ((rect->h + 1) / 2) * ((pitch + 1) / 2);
179  dst = swdata->pixels + swdata->h * swdata->w +
180  ((swdata->h + 1)/2) * ((swdata->w+1) / 2);
181  dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
182  length = (rect->w + 1) / 2;
183  for (row = 0; row < (rect->h + 1)/2; ++row) {
185  src += (pitch + 1)/2;
186  dst += (swdata->w + 1)/2;
187  }
188  }
189  break;
193  {
194  Uint8 *src, *dst;
195  int row;
196  size_t length;
197 
198  src = (Uint8 *) pixels;
199  dst =
200  swdata->planes[0] + rect->y * swdata->pitches[0] +
201  rect->x * 2;
202  length = 4 * ((rect->w + 1) / 2);
203  for (row = 0; row < rect->h; ++row) {
205  src += pitch;
206  dst += swdata->pitches[0];
207  }
208  }
209  break;
212  {
213  if (rect->x == 0 && rect->y == 0 && rect->w == swdata->w && rect->h == swdata->h) {
214  SDL_memcpy(swdata->pixels, pixels,
215  (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
216  } else {
217 
218  Uint8 *src, *dst;
219  int row;
220  size_t length;
221 
222  /* Copy the Y plane */
223  src = (Uint8 *) pixels;
224  dst = swdata->pixels + rect->y * swdata->w + rect->x;
225  length = rect->w;
226  for (row = 0; row < rect->h; ++row) {
228  src += pitch;
229  dst += swdata->w;
230  }
231 
232  /* Copy the next plane */
233  src = (Uint8 *) pixels + rect->h * pitch;
234  dst = swdata->pixels + swdata->h * swdata->w;
235  dst += 2 * ((rect->y + 1)/2) * ((swdata->w + 1) / 2) + 2 * (rect->x/2);
236  length = 2 * ((rect->w + 1) / 2);
237  for (row = 0; row < (rect->h + 1)/2; ++row) {
239  src += 2 * ((pitch + 1)/2);
240  dst += 2 * ((swdata->w + 1)/2);
241  }
242  }
243  }
244  }
245  return 0;
246 }
247 
248 int
250  const Uint8 *Yplane, int Ypitch,
251  const Uint8 *Uplane, int Upitch,
252  const Uint8 *Vplane, int Vpitch)
253 {
254  const Uint8 *src;
255  Uint8 *dst;
256  int row;
257  size_t length;
258 
259  /* Copy the Y plane */
260  src = Yplane;
261  dst = swdata->pixels + rect->y * swdata->w + rect->x;
262  length = rect->w;
263  for (row = 0; row < rect->h; ++row) {
265  src += Ypitch;
266  dst += swdata->w;
267  }
268 
269  /* Copy the U plane */
270  src = Uplane;
271  if (swdata->format == SDL_PIXELFORMAT_IYUV) {
272  dst = swdata->pixels + swdata->h * swdata->w;
273  } else {
274  dst = swdata->pixels + swdata->h * swdata->w +
275  ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
276  }
277  dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
278  length = (rect->w + 1) / 2;
279  for (row = 0; row < (rect->h + 1)/2; ++row) {
281  src += Upitch;
282  dst += (swdata->w + 1)/2;
283  }
284 
285  /* Copy the V plane */
286  src = Vplane;
287  if (swdata->format == SDL_PIXELFORMAT_YV12) {
288  dst = swdata->pixels + swdata->h * swdata->w;
289  } else {
290  dst = swdata->pixels + swdata->h * swdata->w +
291  ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
292  }
293  dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2;
294  length = (rect->w + 1) / 2;
295  for (row = 0; row < (rect->h + 1)/2; ++row) {
297  src += Vpitch;
298  dst += (swdata->w + 1)/2;
299  }
300  return 0;
301 }
302 
303 int
305  void **pixels, int *pitch)
306 {
307  switch (swdata->format) {
312  if (rect
313  && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w
314  || rect->h != swdata->h)) {
315  return SDL_SetError
316  ("YV12, IYUV, NV12, NV21 textures only support full surface locks");
317  }
318  break;
319  }
320 
321  if (rect) {
322  *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
323  } else {
324  *pixels = swdata->planes[0];
325  }
326  *pitch = swdata->pitches[0];
327  return 0;
328 }
329 
330 void
332 {
333 }
334 
335 int
337  Uint32 target_format, int w, int h, void *pixels,
338  int pitch)
339 {
340  int stretch;
341 
342  /* Make sure we're set up to display in the desired format */
343  if (target_format != swdata->target_format && swdata->display) {
344  SDL_FreeSurface(swdata->display);
345  swdata->display = NULL;
346  }
347 
348  stretch = 0;
349  if (srcrect->x || srcrect->y || srcrect->w < swdata->w || srcrect->h < swdata->h) {
350  /* The source rectangle has been clipped.
351  Using a scratch surface is easier than adding clipped
352  source support to all the blitters, plus that would
353  slow them down in the general unclipped case.
354  */
355  stretch = 1;
356  } else if ((srcrect->w != w) || (srcrect->h != h)) {
357  stretch = 1;
358  }
359  if (stretch) {
360  int bpp;
361  Uint32 Rmask, Gmask, Bmask, Amask;
362 
363  if (swdata->display) {
364  swdata->display->w = w;
365  swdata->display->h = h;
366  swdata->display->pixels = pixels;
367  swdata->display->pitch = pitch;
368  } else {
369  /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
370  SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
371  &Bmask, &Amask);
372  swdata->display =
373  SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
374  Gmask, Bmask, Amask);
375  if (!swdata->display) {
376  return (-1);
377  }
378  }
379  if (!swdata->stretch) {
380  /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
381  SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
382  &Bmask, &Amask);
383  swdata->stretch =
384  SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask,
385  Gmask, Bmask, Amask);
386  if (!swdata->stretch) {
387  return (-1);
388  }
389  }
390  pixels = swdata->stretch->pixels;
391  pitch = swdata->stretch->pitch;
392  }
393  if (SDL_ConvertPixels(swdata->w, swdata->h, swdata->format,
394  swdata->planes[0], swdata->pitches[0],
395  target_format, pixels, pitch) < 0) {
396  return -1;
397  }
398  if (stretch) {
399  SDL_Rect rect = *srcrect;
400  SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
401  }
402  return 0;
403 }
404 
405 void
407 {
408  if (swdata) {
409  SDL_free(swdata->pixels);
410  SDL_FreeSurface(swdata->stretch);
411  SDL_FreeSurface(swdata->display);
412  SDL_free(swdata);
413  }
414 }
415 
416 #endif /* SDL_HAVE_YUV */
417 
418 /* vi: set ts=4 sw=4 expandtab: */
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_SoftStretch
#define SDL_SoftStretch
Definition: SDL_dynapi_overrides.h:470
SDL_PIXELFORMAT_NV21
@ SDL_PIXELFORMAT_NV21
Definition: SDL_pixels.h:292
SDL_PIXELFORMAT_UYVY
@ SDL_PIXELFORMAT_UYVY
Definition: SDL_pixels.h:286
NULL
#define NULL
Definition: begin_code.h:167
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:76
SDL_Surface::w
int w
Definition: SDL_surface.h:74
SDL_SW_YUVTexture::stretch
SDL_Surface * stretch
Definition: SDL_yuv_sw_c.h:43
SDL_PIXELFORMAT_YUY2
@ SDL_PIXELFORMAT_YUY2
Definition: SDL_pixels.h:284
SDL_SW_YUVTexture::pitches
Uint16 pitches[3]
Definition: SDL_yuv_sw_c.h:39
SDL_SW_LockYUVTexture
int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:304
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1949
length
GLuint GLsizei GLsizei * length
Definition: SDL_opengl_glext.h:672
SDL_Rect::x
int x
Definition: SDL_rect.h:79
SDL_SW_YUVTexture::h
int h
Definition: SDL_yuv_sw_c.h:35
SDL_yuv_sw_c.h
SDL_PIXELFORMAT_IYUV
@ SDL_PIXELFORMAT_IYUV
Definition: SDL_pixels.h:282
SDL_Rect::w
int w
Definition: SDL_rect.h:80
row
GLenum GLenum void * row
Definition: SDL_opengl_glext.h:3141
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1740
SDL_SW_CopyYUVToRGB
int SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture *swdata, const SDL_Rect *srcrect, Uint32 target_format, int w, int h, void *pixels, int pitch)
Definition: SDL_yuv_sw.c:336
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:75
SDL_CreateRGBSurfaceFrom
#define SDL_CreateRGBSurfaceFrom
Definition: SDL_dynapi_overrides.h:445
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
SDL_PIXELFORMAT_YVYU
@ SDL_PIXELFORMAT_YVYU
Definition: SDL_pixels.h:288
SDL_Rect::y
int y
Definition: SDL_rect.h:79
SDL_SW_UnlockYUVTexture
void SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:331
SDL_Rect::h
int h
Definition: SDL_rect.h:80
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
rect
SDL_Rect rect
Definition: testrelative.c:27
SDL_SW_YUVTexture::display
SDL_Surface * display
Definition: SDL_yuv_sw_c.h:44
SDL_FreeSurface
#define SDL_FreeSurface
Definition: SDL_dynapi_overrides.h:446
SDL_PixelFormatEnumToMasks
#define SDL_PixelFormatEnumToMasks
Definition: SDL_dynapi_overrides.h:278
SDL_assert.h
SDL_SW_DestroyYUVTexture
void SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture *swdata)
Definition: SDL_yuv_sw.c:406
SDL_SW_YUVTexture::format
Uint32 format
Definition: SDL_yuv_sw_c.h:33
SDL_SW_UpdateYUVTexturePlanar
int SDL_SW_UpdateYUVTexturePlanar(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
Definition: SDL_yuv_sw.c:249
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
pixels
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
bpp
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp
Definition: pixman-arm-neon-asm.h:146
SDL_CreateRGBSurface
#define SDL_CreateRGBSurface
Definition: SDL_dynapi_overrides.h:444
SDL_SW_CreateYUVTexture
SDL_SW_YUVTexture * SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
Definition: SDL_yuv_sw.c:33
SDL_Surface::h
int h
Definition: SDL_surface.h:74
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
src
GLenum src
Definition: SDL_opengl_glext.h:1740
SDL_SW_YUVTexture::target_format
Uint32 target_format
Definition: SDL_yuv_sw_c.h:34
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_Rect
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
SDL_SW_QueryYUVTexturePixels
int SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture *swdata, void **pixels, int *pitch)
Definition: SDL_yuv_sw.c:132
SDL_SW_YUVTexture
Definition: SDL_yuv_sw_c.h:32
SDL_PIXELFORMAT_NV12
@ SDL_PIXELFORMAT_NV12
Definition: SDL_pixels.h:290
SDL_PIXELFORMAT_UNKNOWN
@ SDL_PIXELFORMAT_UNKNOWN
Definition: SDL_pixels.h:173
SDL_ConvertPixels
#define SDL_ConvertPixels
Definition: SDL_dynapi_overrides.h:465
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_PIXELFORMAT_YV12
@ SDL_PIXELFORMAT_YV12
Definition: SDL_pixels.h:280
SDL_SW_YUVTexture::pixels
Uint8 * pixels
Definition: SDL_yuv_sw_c.h:36
SDL_SW_YUVTexture::planes
Uint8 * planes[3]
Definition: SDL_yuv_sw_c.h:40
SDL_SW_YUVTexture::w
int w
Definition: SDL_yuv_sw_c.h:35
SDL_SW_UpdateYUVTexture
int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_yuv_sw.c:141
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:734