From: Jon Smirl Date: Fri, 13 May 2005 18:31:35 +0000 (+0000) Subject: First attempt at getting egl support up on dumb framebuffer. X-Git-Tag: mesa-7.8~9246 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7012d01d888d482f2c6ad1180231a482026d213a;p=platform%2Fupstream%2Fmesa.git First attempt at getting egl support up on dumb framebuffer. Seems to be mostly working. Not all of egl API is implemented. --- diff --git a/configs/linux-solo b/configs/linux-solo index 9b739c2..cd9d720 100644 --- a/configs/linux-solo +++ b/configs/linux-solo @@ -15,16 +15,16 @@ CFLAGS = $(DEFINES) -Wmissing-prototypes -g -std=c99 -Wundef -fPIC -ffast-math CXXFLAGS = $(DEFINES) -Wall -O3 -ansi -pedantic -fPIC # Library/program dependencies -DRI_LIB_DEPS = -lm -lpthread -lexpat -ldl +DRI_LIB_DEPS = -lm -lpthread -lexpat -ldl -L$(LIB_DIR) -lEGL -l$(GL_LIB) GL_LIB_DEPS = -lm -lpthread -ldl GLU_LIB_DEPS = -L$(LIB_DIR) -l$(GL_LIB) -lm GLUT_LIB_DEPS = -L$(LIB_DIR) -l$(GLU_LIB) -l$(GL_LIB) -lm APP_LIB_DEPS = -L$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -lm -lpthread # Directories -SRC_DIRS = mesa glx/mini glu glut/mini +SRC_DIRS = mesa egl glx/mini glu glut/mini DRIVER_DIRS = dri -PROGRAM_DIRS = miniglx +PROGRAM_DIRS = miniglx egl -#DRI_DIRS = fb ffb gamma sis savage +#DRI_DIRS = ffb gamma sis savage DRI_DIRS = i810 i830 i915 mach64 mga r128 r200 radeon tdfx unichrome fb diff --git a/include/GLES/egl.h b/include/GLES/egl.h index 64acb72..c4fc4ad 100644 --- a/include/GLES/egl.h +++ b/include/GLES/egl.h @@ -249,11 +249,13 @@ GLAPI EGLBoolean APIENTRY eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, GLAPI EGLBoolean APIENTRY eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value); GLAPI EGLBoolean APIENTRY eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens); GLAPI EGLSurface APIENTRY eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); -GLAPI EGLBoolean APIENTRY eglShowSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface); +GLAPI EGLBoolean APIENTRY eglShowSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode); GLAPI EGLBoolean APIENTRY eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y); +GLAPI EGLBoolean APIENTRY eglQueryDisplayMESA(EGLDisplay dpy, EGLint attrib, EGLint *value); GLAPI EGLBoolean APIENTRY eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value); GLAPI EGLBoolean APIENTRY eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface); GLAPI EGLBoolean APIENTRY eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode); +GLAPI const char * APIENTRY eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode); #endif /* EGL_MESA_screen_surface */ diff --git a/progs/egl/Makefile b/progs/egl/Makefile index 2778866..55efcb4 100644 --- a/progs/egl/Makefile +++ b/progs/egl/Makefile @@ -10,6 +10,7 @@ HEADERS = $(TOP)/include/GLES/egl.h PROGRAMS = \ demo1 \ + demo2 \ eglinfo @@ -28,6 +29,13 @@ demo1.o: demo1.c $(HEADERS) $(CC) -c $(CFLAGS) -I$(TOP)/include demo1.c +demo2: demo2.o $(LIB_DIR)/libEGL.so + $(CC) demo2.o -L$(LIB_DIR) -lEGL $(APP_LIB_DEPS) -o $@ + +demo2.o: demo2.c $(HEADERS) + $(CC) -c $(CFLAGS) -I$(TOP)/include demo2.c + + eglinfo: eglinfo.o $(LIB_DIR)/libEGL.so $(CC) eglinfo.o -L$(LIB_DIR) -lEGL -o $@ diff --git a/progs/egl/demo1.c b/progs/egl/demo1.c index f656b54..8c5a26f 100644 --- a/progs/egl/demo1.c +++ b/progs/egl/demo1.c @@ -46,7 +46,7 @@ main(int argc, char *argv[]) /* EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY); */ - EGLDisplay d = eglGetDisplay("!demo"); + EGLDisplay d = eglGetDisplay("!fb_dri"); assert(d); if (!eglInitialize(d, &maj, &min)) { diff --git a/progs/egl/eglinfo.c b/progs/egl/eglinfo.c index a80df6c..e907d13 100644 --- a/progs/egl/eglinfo.c +++ b/progs/egl/eglinfo.c @@ -132,7 +132,8 @@ int main(int argc, char *argv[]) { int maj, min; - EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY); +// EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY); + EGLDisplay d = eglGetDisplay("!fb_dri"); if (!eglInitialize(d, &maj, &min)) { printf("eglinfo: eglInitialize failed\n"); diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c index e5164d6..bb5ea19 100644 --- a/src/egl/drivers/demo/demo.c +++ b/src/egl/drivers/demo/demo.c @@ -56,14 +56,14 @@ demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) EGLint i; /* Create a screen */ - scrn = _eglNewScreen(); + scrn = calloc(1, sizeof(*scrn)); _eglAddScreen(disp, scrn); /* Create the screen's modes - silly example */ - _eglAddMode(scrn, 1600, 1200, 32, 72 * 1000); - _eglAddMode(scrn, 1280, 1024, 32, 72 * 1000); - _eglAddMode(scrn, 1280, 1024, 16, 72 * 1000); - _eglAddMode(scrn, 1024, 768, 32, 72 * 1000); + _eglAddMode(scrn, 1600, 1200, 72 * 1000); + _eglAddMode(scrn, 1280, 1024, 72 * 1000); + _eglAddMode(scrn, 1280, 1024, 72 * 1000); + _eglAddMode(scrn, 1024, 768, 72 * 1000); /* Create the display's visual configs - silly example */ for (i = 0; i < 4; i++) { diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index b0bd1ee..0be901c 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -346,8 +346,18 @@ void (* APIENTRY eglGetProcAddress(const char *procname))() { "eglWaitGL", (_EGLProc) eglWaitGL }, { "eglWaitNative", (_EGLProc) eglWaitNative }, /* Extensions */ - { "eglShowSurfaceMESA", (_EGLProc) NULL }, - { "eglGetModesMESA", (_EGLProc) NULL }, + { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA }, + { "eglGetModesMESA", (_EGLProc) eglGetModesMESA }, + { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA }, + { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA }, + { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA }, + { "eglShowSurfaceMESA", (_EGLProc) eglShowSurfaceMESA }, + { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA }, + { "eglQueryDisplayMESA", (_EGLProc) eglQueryDisplayMESA }, + { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA }, + { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA }, + { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA }, + { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA }, { NULL, NULL } }; EGLint i; @@ -418,35 +428,67 @@ eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EG EGLSurface eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { - return EGL_FALSE; + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->CreateScreenSurfaceMESA(drv, dpy, config, attrib_list); } EGLBoolean -eglShowSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface) +eglShowSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode) { - return EGL_FALSE; + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->ShowSurfaceMESA(drv, dpy, screen, surface, mode); } EGLBoolean -eglScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA mode) +eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y) { - return EGL_FALSE; + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->ScreenPositionMESA(drv, dpy, screen, x, y); +} + + +EGLBoolean +eglQueryDisplayMESA(EGLDisplay dpy, EGLint attrib, EGLint *value) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->QueryDisplayMESA(drv, dpy, attrib, value); +} + + +EGLBoolean +eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->QueryScreenMESA(drv, dpy, screen, attribute, value); } EGLBoolean eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface) { - return EGL_FALSE; + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->QueryScreenSurfaceMESA(drv, dpy, screen, surface); } EGLBoolean -eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value) +eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode) { - return EGL_FALSE; + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->QueryScreenModeMESA(drv, dpy, screen, mode); } +const char * +eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->QueryModeStringMESA(drv, dpy, mode); +} + + + + + diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index 0fb7e26..ff9a647 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "eglconfig.h" @@ -19,19 +20,19 @@ _eglInitConfig(_EGLConfig *config, EGLint id) { memset(config, 0, sizeof(*config)); config->Handle = id; - SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id); - SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); - SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE, EGL_NONE); - SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_CONFIG_ID, id); + _eglSetConfigAtrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + _eglSetConfigAtrib(config, EGL_TRANSPARENT_TYPE, EGL_NONE); + _eglSetConfigAtrib(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE); + _eglSetConfigAtrib(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE); } @@ -77,6 +78,79 @@ _eglAddConfig(_EGLDisplay *display, const _EGLConfig *config) } +extern void +_eglSetConfigAtrib(_EGLConfig *config, EGLint attr, EGLint val) +{ + config->Attrib[attr - FIRST_ATTRIB] = val; + + switch (attr) { + case EGL_BUFFER_SIZE: + config->glmode.rgbBits = val; + break; + case EGL_ALPHA_SIZE: + config->glmode.alphaBits = val; + break; + case EGL_BLUE_SIZE: + config->glmode.blueBits = val; + break; + case EGL_GREEN_SIZE: + config->glmode.greenBits = val; + break; + case EGL_RED_SIZE: + config->glmode.redBits = val; + break; + case EGL_DEPTH_SIZE: + config->glmode.depthBits = val; + break; + case EGL_STENCIL_SIZE: + config->glmode.stencilBits = val; + break; + case EGL_CONFIG_CAVEAT: + break; + case EGL_CONFIG_ID: + break; + case EGL_LEVEL: + break; + case EGL_MAX_PBUFFER_HEIGHT: + break; + case EGL_MAX_PBUFFER_PIXELS: + break; + case EGL_MAX_PBUFFER_WIDTH: + break; + case EGL_NATIVE_RENDERABLE: + break; + case EGL_NATIVE_VISUAL_ID: + break; + case EGL_NATIVE_VISUAL_TYPE: + break; + case EGL_SAMPLES: + break; + case EGL_SAMPLE_BUFFERS: + break; + case EGL_SURFACE_TYPE: + break; + case EGL_TRANSPARENT_TYPE: + break; + case EGL_TRANSPARENT_BLUE_VALUE: + break; + case EGL_TRANSPARENT_GREEN_VALUE: + break; + case EGL_TRANSPARENT_RED_VALUE: + break; + case EGL_NONE: + break; + case EGL_BIND_TO_TEXTURE_RGB: + break; + case EGL_BIND_TO_TEXTURE_RGBA: + break; + case EGL_MIN_SWAP_INTERVAL: + break; + case EGL_MAX_SWAP_INTERVAL: + break; + default: + break; + } +} /** * Parse the attrib_list to fill in the fields of the given _egl_config @@ -310,3 +384,234 @@ _eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint confi } return EGL_TRUE; } + + +/** + * Creates a set of \c __GLcontextModes that a driver will expose. + * + * A set of \c __GLcontextModes will be created based on the supplied + * parameters. The number of modes processed will be 2 * + * \c num_depth_stencil_bits * \c num_db_modes. + * + * For the most part, data is just copied from \c depth_bits, \c stencil_bits, + * \c db_modes, and \c visType into each \c __GLcontextModes element. + * However, the meanings of \c fb_format and \c fb_type require further + * explanation. The \c fb_format specifies which color components are in + * each pixel and what the default order is. For example, \c GL_RGB specifies + * that red, green, blue are available and red is in the "most significant" + * position and blue is in the "least significant". The \c fb_type specifies + * the bit sizes of each component and the actual ordering. For example, if + * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] + * are the blue value, bits [10:5] are the green value, and bits [4:0] are + * the red value. + * + * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either + * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the + * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or + * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as + * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 + * still uses 32-bits. + * + * If in doubt, look at the tables used in the function. + * + * \param ptr_to_modes Pointer to a pointer to a linked list of + * \c __GLcontextModes. Upon completion, a pointer to + * the next element to be process will be stored here. + * If the function fails and returns \c GL_FALSE, this + * value will be unmodified, but some elements in the + * linked list may be modified. + * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, + * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. + * \param fb_type Type of the pixels in the framebuffer. Currently only + * \c GL_UNSIGNED_SHORT_5_6_5, + * \c GL_UNSIGNED_SHORT_5_6_5_REV, + * \c GL_UNSIGNED_INT_8_8_8_8, and + * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. + * \param depth_bits Array of depth buffer sizes to be exposed. + * \param stencil_bits Array of stencil buffer sizes to be exposed. + * \param num_depth_stencil_bits Number of entries in both \c depth_bits and + * \c stencil_bits. + * \param db_modes Array of buffer swap modes. If an element has a + * value of \c GLX_NONE, then it represents a + * single-buffered mode. Other valid values are + * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and + * \c GLX_SWAP_UNDEFINED_OML. See the + * GLX_OML_swap_method extension spec for more details. + * \param num_db_modes Number of entries in \c db_modes. + * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or + * \c GLX_DIRECT_COLOR. + * + * \returns + * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only + * cause of failure is a bad parameter (i.e., unsupported \c fb_format or + * \c fb_type). + * + * \todo + * There is currently no way to support packed RGB modes (i.e., modes with + * exactly 3 bytes per pixel) or floating-point modes. This could probably + * be done by creating some new, private enums with clever names likes + * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, + * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. + */ +GLboolean +_eglFillInConfigs(_EGLConfig * configs, + GLenum fb_format, GLenum fb_type, + const u_int8_t * depth_bits, const u_int8_t * stencil_bits, + unsigned num_depth_stencil_bits, + const GLenum * db_modes, unsigned num_db_modes, + int visType) { + static const u_int8_t bits_table[3][4] = { + /* R G B A */ + { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ + { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ + { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ + }; + + /* The following arrays are all indexed by the fb_type masked with 0x07. + * Given the four supported fb_type values, this results in valid array + * indices of 3, 4, 5, and 7. + */ + static const u_int32_t masks_table_rgb[8][4] = { + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */ + {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */ + {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */ + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */ + }; + + static const u_int32_t masks_table_rgba[8][4] = { + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */ + {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */ + {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */ + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */ + }; + + static const u_int32_t masks_table_bgr[8][4] = { + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */ + {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */ + {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */ + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */ + }; + + static const u_int32_t masks_table_bgra[8][4] = { + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */ + {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */ + {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */ + {0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */ + }; + + static const u_int8_t bytes_per_pixel[8] = { + 0, 0, 0, 2, 2, 4, 0, 4 + }; + + const u_int8_t * bits; + const u_int32_t * masks; + const int index = fb_type & 0x07; + _EGLConfig *config; + unsigned i; + unsigned j; + unsigned k; + + if ( bytes_per_pixel[index] == 0 ) { + fprintf(stderr, "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.\n", + __FUNCTION__, __LINE__, fb_type); + return GL_FALSE; + } + + /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and + * the _REV versions. + * + * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. + */ + switch ( fb_format ) { + case GL_RGB: + bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1]; + masks = masks_table_rgb[index]; + break; + + case GL_RGBA: + bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2]; + masks = masks_table_rgba[index]; + break; + + case GL_BGR: + bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1]; + masks = masks_table_bgr[index]; + break; + + case GL_BGRA: + bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2]; + masks = masks_table_bgra[index]; + break; + + default: + fprintf(stderr, "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.\n", + __FUNCTION__, __LINE__, fb_format); + return GL_FALSE; + } + + config = configs; + for (k = 0; k < num_depth_stencil_bits; k++) { + for (i = 0; i < num_db_modes; i++) { + for (j = 0; j < 2; j++) { + + _eglSetConfigAtrib(config, EGL_RED_SIZE, bits[0]); + _eglSetConfigAtrib(config, EGL_GREEN_SIZE, bits[1]); + _eglSetConfigAtrib(config, EGL_BLUE_SIZE, bits[2]); + _eglSetConfigAtrib(config, EGL_ALPHA_SIZE, bits[3]); + config->glmode.redMask = masks[0]; + config->glmode.greenMask = masks[1]; + config->glmode.blueMask = masks[2]; + config->glmode.alphaMask = masks[3]; + _eglSetConfigAtrib(config, EGL_BUFFER_SIZE, config->glmode.redBits + config->glmode.greenBits + + config->glmode.blueBits + config->glmode.alphaBits); + + config->glmode.accumRedBits = 16 * j; + config->glmode.accumGreenBits = 16 * j; + config->glmode.accumBlueBits = 16 * j; + config->glmode.accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; + config->glmode.visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; + + _eglSetConfigAtrib(config, EGL_STENCIL_SIZE, stencil_bits[k]); + _eglSetConfigAtrib(config, EGL_DEPTH_SIZE, depth_bits[k]); + + config->glmode.visualType = visType; + config->glmode.renderType = GLX_RGBA_BIT; + config->glmode.drawableType = GLX_WINDOW_BIT; + config->glmode.rgbMode = GL_TRUE; + + if (db_modes[i] == GLX_NONE) { + config->glmode.doubleBufferMode = GL_FALSE; + } else { + config->glmode.doubleBufferMode = GL_TRUE; + config->glmode.swapMethod = db_modes[i]; + } + + config->glmode.haveAccumBuffer = ((config->glmode.accumRedBits + + config->glmode.accumGreenBits + + config->glmode.accumBlueBits + + config->glmode.accumAlphaBits) > 0); + config->glmode.haveDepthBuffer = (config->glmode.depthBits > 0); + config->glmode.haveStencilBuffer = (config->glmode.stencilBits > 0); + + config++; + } + } + } + return GL_TRUE; +} diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h index 874edcd..5d4d458 100644 --- a/src/egl/main/eglconfig.h +++ b/src/egl/main/eglconfig.h @@ -3,6 +3,7 @@ #include "egltypedefs.h" +#include "GL/internal/glcore.h" #define MAX_ATTRIBS 100 @@ -13,11 +14,11 @@ struct _egl_config { EGLConfig Handle; /* the public/opaque handle which names this config */ EGLint Attrib[MAX_ATTRIBS]; + __GLcontextModes glmode; }; -#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL) #define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB]) @@ -33,6 +34,10 @@ extern _EGLConfig * _eglAddConfig(_EGLDisplay *display, const _EGLConfig *config); +extern void +_eglSetConfigAtrib(_EGLConfig *config, EGLint attr, EGLint val); + + extern EGLBoolean _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list); @@ -57,4 +62,12 @@ extern EGLBoolean _eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +extern GLboolean +_eglFillInConfigs( _EGLConfig *configs, + GLenum fb_format, GLenum fb_type, + const u_int8_t * depth_bits, const u_int8_t * stencil_bits, + unsigned num_depth_stencil_bits, + const GLenum * db_modes, unsigned num_db_modes, + int visType ); + #endif /* EGLCONFIG_INCLUDED */ diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index e7d833e..1d12a40 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -15,7 +15,7 @@ void _eglInitContext(_EGLContext *ctx) { - /* just init to zer for now */ + /* just init to zero for now */ memset(ctx, 0, sizeof(_EGLContext)); } diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 0f29810..53b4ba9 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -62,10 +62,17 @@ _eglGetCurrentDisplay(void) void -_eglDeleteDisplay(_EGLDisplay *disp) +_eglCleanupDisplay(_EGLDisplay *disp) { /* XXX incomplete */ free(disp->Configs); - free(disp); + free(disp->Name); + /* driver deletes _EGLDisplay */ } + +EGLBoolean +_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value) +{ + return EGL_FALSE; +} diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 55555e6..1a03fdd 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -33,7 +33,12 @@ _eglGetCurrentDisplay(void); extern void -_eglDeleteDisplay(_EGLDisplay *disp); +_eglCleanupDisplay(_EGLDisplay *disp); + + +extern EGLBoolean +_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value); + #endif /* EGLDISPLAY_INCLUDED */ diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c index 870c062..e2120e3 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -12,7 +12,7 @@ #include "eglsurface.h" -const char *DefaultDriverName = "demo"; +const char *DefaultDriverName = "demodriver"; /** @@ -75,7 +75,7 @@ _eglOpenDriver(_EGLDisplay *dpy, const char *driverName) char driverFilename[1000]; /* XXX also prepend a directory path??? */ - sprintf(driverFilename, "%sdriver.so", driverName); + sprintf(driverFilename, "%s.so", driverName); #if 1 lib = dlopen(driverFilename, RTLD_NOW); @@ -189,9 +189,11 @@ _eglInitDriverFallbacks(_EGLDriver *drv) drv->CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA; drv->ShowSurfaceMESA = _eglShowSurfaceMESA; drv->ScreenPositionMESA = _eglScreenPositionMESA; + drv->QueryDisplayMESA = _eglQueryDisplayMESA; drv->QueryScreenMESA = _eglQueryScreenMESA; drv->QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA; drv->QueryScreenModeMESA = _eglQueryScreenModeMESA; + drv->QueryModeStringMESA = _eglQueryModeStringMESA; } diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h index e931559..45bee94 100644 --- a/src/egl/main/egldriver.h +++ b/src/egl/main/egldriver.h @@ -45,12 +45,13 @@ typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenM typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value); typedef EGLBoolean (*GetScreensMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens); typedef EGLSurface (*CreateScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); -typedef EGLBoolean (*ShowSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface); +typedef EGLBoolean (*ShowSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode); typedef EGLBoolean (*ScreenPositionMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y); +typedef EGLBoolean (*QueryDisplayMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value); typedef EGLBoolean (*QueryScreenMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value); typedef EGLBoolean (*QueryScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface); typedef EGLBoolean (*QueryScreenModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode); - +typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode); /** @@ -106,9 +107,11 @@ struct _egl_driver CreateScreenSurfaceMESA_t CreateScreenSurfaceMESA; ShowSurfaceMESA_t ShowSurfaceMESA; ScreenPositionMESA_t ScreenPositionMESA; + QueryDisplayMESA_t QueryDisplayMESA; QueryScreenMESA_t QueryScreenMESA; QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA; QueryScreenModeMESA_t QueryScreenModeMESA; + QueryModeStringMESA_t QueryModeStringMESA; }; diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c index 857fa38..26ea6bd 100644 --- a/src/egl/main/eglmode.c +++ b/src/egl/main/eglmode.c @@ -1,5 +1,7 @@ #include #include +#include + #include "egldisplay.h" #include "egldriver.h" #include "eglmode.h" @@ -10,6 +12,16 @@ #define MIN2(A, B) (((A) < (B)) ? (A) : (B)) +static char * +my_strdup(const char *s) +{ + int l = strlen(s); + char *s2 = malloc(l + 1); + strcpy(s2, s); + return s2; +} + + /** * Given an EGLModeMESA handle, return the corresponding _EGLMode object * or null if non-existant. @@ -44,7 +56,7 @@ _eglLookupMode(EGLDisplay dpy, EGLModeMESA mode) */ _EGLMode * _eglAddMode(_EGLScreen *screen, EGLint width, EGLint height, - EGLint depth, EGLint refreshRate) + EGLint refreshRate, char *name) { EGLint n; _EGLMode *newModes; @@ -52,7 +64,6 @@ _eglAddMode(_EGLScreen *screen, EGLint width, EGLint height, assert(screen); assert(width > 0); assert(height > 0); - assert(depth > 0); assert(refreshRate > 0); n = screen->NumModes; @@ -62,9 +73,9 @@ _eglAddMode(_EGLScreen *screen, EGLint width, EGLint height, screen->Modes[n].Handle = n + 1; screen->Modes[n].Width = width; screen->Modes[n].Height = height; - screen->Modes[n].Depth = depth; screen->Modes[n].RefreshRate = refreshRate; screen->Modes[n].Stereo = EGL_FALSE; + screen->Modes[n].Name = my_strdup(name); screen->NumModes++; return screen->Modes + n; } @@ -176,3 +187,13 @@ _eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, } return EGL_TRUE; } + + +const char * +_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode) +{ + _EGLMode *m = _eglLookupMode(dpy, mode); + return m->Name; +} + + diff --git a/src/egl/main/eglmode.h b/src/egl/main/eglmode.h index fa6d8e4..71adef4 100644 --- a/src/egl/main/eglmode.h +++ b/src/egl/main/eglmode.h @@ -11,9 +11,9 @@ struct _egl_mode { EGLModeMESA Handle; /* the public/opaque handle which names this mode */ EGLint Width, Height; /* size in pixels */ - EGLint Depth; /* bits per pixel */ EGLint RefreshRate; /* rate * 1000.0 */ EGLBoolean Stereo; + char *Name; /* Other possible attributes */ /* interlaced */ @@ -27,7 +27,7 @@ _eglLookupMode(EGLDisplay dpy, EGLModeMESA mode); extern _EGLMode * _eglAddMode(_EGLScreen *screen, EGLint width, EGLint height, - EGLint depth, EGLint refreshRate); + EGLint refreshRate, char *name); extern EGLBoolean @@ -46,5 +46,8 @@ _eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value); +extern const char * +_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode); + #endif /* EGLMODE_INCLUDED */ diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c index 66baa31..406ad1b 100644 --- a/src/egl/main/eglscreen.c +++ b/src/egl/main/eglscreen.c @@ -13,9 +13,12 @@ #include #include +#include + #include "egldisplay.h" #include "eglglobals.h" #include "eglmode.h" +#include "eglconfig.h" #include "eglsurface.h" #include "eglscreen.h" @@ -23,10 +26,11 @@ /** * Return a new _EGLScreen object. */ -_EGLScreen * -_eglNewScreen(void) +void +_eglInitScreen(_EGLScreen *screen) { - return (_EGLScreen *) calloc(1, sizeof(_EGLScreen)); + /* just init to zero for now */ + memset(screen, 0, sizeof(_EGLScreen)); } @@ -101,14 +105,10 @@ _eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, } -/** - * Create a drawing surface which can be directly displayed on a screen. - */ EGLSurface -_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +_eglInitScreenSurfaceMESA(_EGLSurface *surf, _EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { - _EGLSurface *surf; EGLint width = 0, height = 0; EGLint i; @@ -132,11 +132,11 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_NO_SURFACE; } - surf = (_EGLSurface *) malloc(sizeof(_EGLSurface)); _eglInitSurface(surf); surf->Width = width; surf->Height = height; surf->Type = EGL_SCREEN_BIT_MESA; + surf->Config = _eglLookupConfig(drv, dpy, config); /* insert into hash table */ _eglSaveSurface(surf); @@ -147,6 +147,25 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, /** + * Create a drawing surface which can be directly displayed on a screen. + */ +EGLSurface +_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + _EGLSurface *surf; + EGLSurface surface; + + surf = (_EGLSurface *) malloc(sizeof(_EGLSurface)); + surface = _eglInitScreenSurfaceMESA(surf, drv, dpy, config, attrib_list); + if (surface == EGL_NO_SURFACE) + free(surf); + + return surface; +} + + +/** * Show the given surface on the named screen. * If surface is EGL_NO_SURFACE, disable the screen's output. * @@ -155,31 +174,23 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, */ EGLBoolean _eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, - EGLSurface surface) + EGLSurface surface, EGLModeMESA m) { _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - _EGLMode *mode; + _EGLMode *mode = _eglLookupMode(dpy, m); if (!scrn) { _eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA"); return EGL_FALSE; } - - /* - * XXX: Check if the surface's configuration is compatible with the - * current screen mode. - */ - - mode = scrn->CurrentMode; - if (mode == EGL_NO_MODE_MESA) { - _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA(no current mode)"); + if (!mode) { + _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA"); return EGL_FALSE; } if (surface == EGL_NO_SURFACE) { scrn->CurrentSurface = NULL; - } - else { + } else { _EGLSurface *surf = _eglLookupSurface(surface); if (!surf || surf->Type != EGL_SCREEN_BIT_MESA) { _eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA"); @@ -192,8 +203,8 @@ _eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, } scrn->CurrentSurface = surf; + scrn->CurrentMode = mode; } - return EGL_TRUE; } @@ -299,11 +310,20 @@ _eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, } - void -_eglDeleteScreen(_EGLScreen *scrn) +_eglDestroyScreenModes(_EGLScreen *scrn) { free(scrn->Modes); +} + + +/** + * Default fallback routine - drivers should usually override this. + */ +void +_eglDestroyScreen(_EGLScreen *scrn) +{ + _eglDestroyScreenModes(scrn); free(scrn); } diff --git a/src/egl/main/eglscreen.h b/src/egl/main/eglscreen.h index 1d1856b..1dff069 100644 --- a/src/egl/main/eglscreen.h +++ b/src/egl/main/eglscreen.h @@ -19,8 +19,8 @@ struct _egl_screen }; -extern _EGLScreen * -_eglNewScreen(void); +extern void +_eglInitScreen(_EGLScreen *screen); extern _EGLScreen * @@ -36,11 +36,15 @@ _eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLi extern EGLSurface +_eglInitScreenSurfaceMESA(_EGLSurface *surf, _EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list); + +extern EGLSurface _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); extern EGLBoolean -_eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface); +_eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode); extern EGLBoolean @@ -69,7 +73,11 @@ _eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLin extern void -_eglDeleteScreen(_EGLScreen *scrn); +_eglDestroyScreenModes(_EGLScreen *scrn); + + +extern void +_eglDestroyScreen(_EGLScreen *scrn); #endif /* EGLSCREEN_INCLUDED */ diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template index 81c0456..027572c 100644 --- a/src/mesa/drivers/dri/Makefile.template +++ b/src/mesa/drivers/dri/Makefile.template @@ -56,7 +56,8 @@ SHARED_INCLUDES = \ -I$(TOP)/src/mesa/transform \ -I$(TOP)/src/mesa/shader \ -I$(TOP)/src/mesa/swrast \ - -I$(TOP)/src/mesa/swrast_setup + -I$(TOP)/src/mesa/swrast_setup \ + -I$(TOP)/src/egl/main ##### RULES ##### diff --git a/src/mesa/drivers/dri/fb/Makefile b/src/mesa/drivers/dri/fb/Makefile index 618f024..12465c9 100644 --- a/src/mesa/drivers/dri/fb/Makefile +++ b/src/mesa/drivers/dri/fb/Makefile @@ -6,7 +6,8 @@ include $(TOP)/configs/current LIBNAME = fb_dri.so DRIVER_SOURCES = \ - fb_dri.c + fb_dri.c \ + fb_egl.c C_SOURCES = \ $(COMMON_SOURCES) \ diff --git a/src/mesa/drivers/dri/fb/fb_dri.c b/src/mesa/drivers/dri/fb/fb_dri.c index 264f8f0..eafed1f 100644 --- a/src/mesa/drivers/dri/fb/fb_dri.c +++ b/src/mesa/drivers/dri/fb/fb_dri.c @@ -58,6 +58,7 @@ #include "tnl/t_pipeline.h" #include "drivers/common/driverfuncs.h" +void fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis); typedef struct { GLcontext *glCtx; /* Mesa context */ @@ -242,7 +243,7 @@ init_core_functions( struct dd_function_table *functions ) -static void +void fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) { ASSERT(drb->Base.InternalFormat == GL_RGBA);