Source

pygame / src / overlay.c

Full commit
/*
 *   A part of the pydfb module. Provides interface for basic overlay
 *			manipulation functions.
 *      In this implementation overlay can use only one layer out of maximum
 *      possible. After getting overlay, no overlay can be created.
 *
 *					Copyright (C) 2002-2003  Dmitry Borisov
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Dmitry Borisov
*/


#include <Python.h>
#include "pygame.h"
#include "pygamedocs.h"

typedef struct
{
  PyObject_HEAD
	SDL_Overlay *cOverlay;
	GAME_Rect cRect;
} PyGameOverlay;


static void
overlay_dealloc(PyGameOverlay *self)
{
	if(SDL_WasInit(SDL_INIT_VIDEO) && self->cOverlay)
		SDL_FreeYUVOverlay(self->cOverlay);

	PyObject_Free((PyObject*)self);
}


static PyObject* Overlay_SetLocation(PyGameOverlay *self, PyObject *args)
{
        GAME_Rect *rect, temp;
    
        rect = GameRect_FromObject(args, &temp);
        if(!rect)
            return RAISE(PyExc_TypeError, "Invalid rectstyle argument");
        
        self->cRect.x = rect->x;
        self->cRect.y = rect->y;
        self->cRect.w = rect->w;
        self->cRect.h = rect->h;

	RETURN_NONE
}


static PyObject* Overlay_Display(PyGameOverlay *self, PyObject *args)
{
    SDL_Rect cRect;
    	// Parse data params for frame
	int ls_y, ls_u, ls_v, y;
	unsigned char *src_y=0, *src_u=0, *src_v=0;
	
	if(PyTuple_Size(args))
	{
        	if(!PyArg_ParseTuple(args, "(s#s#s#)", &src_y, &ls_y, &src_u, &ls_u, &src_v, &ls_v))
        		return NULL;
    }

    if(src_y)
	{
                Uint8 *dst_y=0, *dst_u=0, *dst_v=0;
		SDL_LockYUVOverlay( self->cOverlay );

		// No clipping at this time( only support for YUV420 )

                dst_y = self->cOverlay->pixels[ 0 ];
                dst_v = self->cOverlay->pixels[ 1 ];
                dst_u = self->cOverlay->pixels[ 2 ];

		for (y=0; y< self->cOverlay->h; y++)
		{
			memcpy( dst_y, src_y, self->cOverlay->w );

			src_y += ls_y / self->cOverlay->h;
			dst_y += self->cOverlay->pitches[ 0 ];

			if (!(y & 1)) {
				src_u += ( ls_u* 2 )/self->cOverlay->h;
				src_v += ( ls_v* 2 )/self->cOverlay->h;
				dst_u += self->cOverlay->pitches[ 1 ];
				dst_v += self->cOverlay->pitches[ 2 ];
			}
			else
			{
				memcpy( dst_u, src_u, ( ls_u* 2 )/self->cOverlay->h );
				memcpy( dst_v, src_v, ( ls_v* 2 )/self->cOverlay->h );
			}
		}

		SDL_UnlockYUVOverlay( self->cOverlay );
	}

    cRect.x = self->cRect.x;
    cRect.y = self->cRect.y;
    cRect.w = self->cRect.w;
    cRect.h = self->cRect.h;
    SDL_DisplayYUVOverlay(self->cOverlay, &cRect);

	RETURN_NONE
}



static PyObject* Overlay_GetHardware(PyGameOverlay *self, PyObject *args)
{
    return PyInt_FromLong(self->cOverlay->hw_overlay);
}



PyObject* Overlay_New(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	int pixelformat;
	PyGameOverlay *self;
	int w, h;
        SDL_Surface *screen;
	if(!PyArg_ParseTuple(args, "i(ii)", &pixelformat, &w, &h))
		return NULL;

	if(!SDL_WasInit(SDL_INIT_VIDEO))
		return RAISE(PyExc_SDLError, "cannot create overlay without pygame.display initialized");

        screen = SDL_GetVideoSurface();
        if(!screen)
            return RAISE(PyExc_SDLError, "Display mode not set");
        
	// Create new Overlay object
	self= (PyGameOverlay *)type->tp_alloc(type, 0);
        if( !self )
		return NULL;

	// Create layer with desired format
	self->cOverlay = SDL_CreateYUVOverlay(w, h, pixelformat, screen);
	if( !self->cOverlay )
		return RAISE(PyExc_SDLError, "Cannot create overlay");

	self->cRect.x= 0;
	self->cRect.y= 0;
	self->cRect.w= w;
	self->cRect.h= h;

	return (PyObject*)self;
}


static PyMethodDef Overlay_methods[] = {
  {"set_location", (PyCFunction)Overlay_SetLocation, METH_VARARGS, DOC_OVERLAYSETLOCATION},
  {"display", (PyCFunction)Overlay_Display, METH_VARARGS, DOC_OVERLAYDISPLAY},
  {"get_hardware", (PyCFunction)Overlay_GetHardware, METH_NOARGS, DOC_OVERLAYGETHARDWARE},
	{NULL}  /* Sentinel */
};


PyTypeObject PyOverlay_Type =
{
	PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "pygame.overlay",        /*tp_name*/
    sizeof(PyGameOverlay),      /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    0,												/*tp_dealloc*/
	0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,   /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
    DOC_PYGAMEOVERLAY,           /* tp_doc */
    0,		               /* tp_traverse */
    0,		               /* tp_clear */
    0,		               /* tp_richcompare */
    0,		               /* tp_weaklistoffset */
    0,		               /* tp_iter */
    0,		               /* tp_iternext */
    Overlay_methods,             /* tp_methods */
    0,             /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    0,    /* tp_init */
    0,       /* tp_alloc */
    Overlay_New,			   /* tp_new */
};

static PyMethodDef overlay_methods[] =
{
	{ NULL, NULL }
};


PYGAME_EXPORT
void initoverlay(void)
{
	PyObject *module;
	module = Py_InitModule("overlay", overlay_methods );

	PyOverlay_Type.ob_type = &PyType_Type;
	PyOverlay_Type.tp_dealloc = (destructor)overlay_dealloc;
	PyOverlay_Type.tp_alloc =PyType_GenericAlloc;
	PyOverlay_Type.tp_getattro = PyObject_GenericGetAttr;
	Py_INCREF((PyObject *)&PyOverlay_Type);
	PyType_Init(PyOverlay_Type);

    /* create the module reference */
	PyModule_AddObject(module, "Overlay", (PyObject *)&PyOverlay_Type);

	import_pygame_base();
	import_pygame_rect();    
}