Merge branch 'fdva-master'
diff --git a/configure.ac b/configure.ac
index fce164c..8792dcc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@
           [libva_major_version.libva_minor_version.libva_micro_version])
 
 # if the library source code has changed, increment revision
-m4_define([libva_lt_revision], [3])
+m4_define([libva_lt_revision], [4])
 # if any interface was added/removed/changed, then inc current, reset revision
 m4_define([libva_lt_current], [1])
 # if any interface was added since last public release, then increment age
@@ -103,9 +103,9 @@
 PKG_CHECK_MODULES(GEN4ASM, [intel-gen4asm >= 1.0], [gen4asm=yes], [gen4asm=no])
 AM_CONDITIONAL(HAVE_GEN4ASM, test x$gen4asm = xyes)
 
-# Check for libdrm >= 2.4 (needed for i965_drv_video.so)
-if test x$enable_i965_driver = xyes && ! $PKG_CONFIG --atleast-version=2.4 libdrm; then
-    AC_MSG_WARN([libdrm < 2.4 found, disabling build of i965 video driver])
+# Check for libdrm >= 2.4.21 (needed for i965_drv_video.so)
+if test x$enable_i965_driver = xyes && ! $PKG_CONFIG --atleast-version=2.4.21 libdrm; then
+    AC_MSG_WARN([libdrm < 2.4.21 found, disabling build of i965 video driver])
     enable_i965_driver=no
 fi
 AM_CONDITIONAL(BUILD_I965_DRIVER, test x$enable_i965_driver = xyes)
diff --git a/dummy_drv_video/dummy_drv_video.c b/dummy_drv_video/dummy_drv_video.c
index ed72824..90eb9c6 100644
--- a/dummy_drv_video/dummy_drv_video.c
+++ b/dummy_drv_video/dummy_drv_video.c
@@ -1040,7 +1040,7 @@
 VAStatus dummy_PutSurface(
    		VADriverContextP ctx,
 		VASurfaceID surface,
-		Drawable draw, /* X Drawable */
+		void *draw, /* X Drawable */
 		short srcx,
 		short srcy,
 		unsigned short srcw,
@@ -1055,6 +1055,10 @@
 	)
 {
     /* TODO */
+    Drawable drawable = (Drawable)draw;
+
+    (void)drawable;
+    
     return VA_STATUS_ERROR_UNKNOWN;
 }
 
diff --git a/i965_drv_video/Makefile.am b/i965_drv_video/Makefile.am
index cdf9d95..058b525 100644
--- a/i965_drv_video/Makefile.am
+++ b/i965_drv_video/Makefile.am
@@ -22,7 +22,7 @@
 
 SUBDIRS = shaders
 
-AM_CFLAGS = -Wall -I$(top_srcdir)/va -I$(top_srcdir)/va/x11 @DRM_CFLAGS@
+AM_CFLAGS = -Wall -I$(top_srcdir) -I$(top_srcdir)/va -I$(top_srcdir)/va/x11 @DRM_CFLAGS@
 
 i965_drv_video_la_LTLIBRARIES = i965_drv_video.la
 i965_drv_video_ladir = @LIBVA_DRIVERS_PATH@
diff --git a/i965_drv_video/i965_drv_video.c b/i965_drv_video/i965_drv_video.c
index ace2181..104c105 100644
--- a/i965_drv_video/i965_drv_video.c
+++ b/i965_drv_video/i965_drv_video.c
@@ -54,6 +54,22 @@
     I965_SURFACETYPE_INDEXED
 };
 
+/* List of supported image formats */
+typedef struct {
+    unsigned int        type;
+    VAImageFormat       va_format;
+} i965_image_format_map_t;
+
+static const i965_image_format_map_t
+i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = {
+    { I965_SURFACETYPE_YUV,
+      { VA_FOURCC('Y','V','1','2'), VA_LSB_FIRST, 12, } },
+    { I965_SURFACETYPE_YUV,
+      { VA_FOURCC('I','4','2','0'), VA_LSB_FIRST, 12, } },
+    { I965_SURFACETYPE_YUV,
+      { VA_FOURCC('N','V','1','2'), VA_LSB_FIRST, 12, } },
+};
+
 /* List of supported subpicture formats */
 typedef struct {
     unsigned int        type;
@@ -70,13 +86,21 @@
     { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A4P4_UNORM,
       { VA_FOURCC('A','I','4','4'), VA_MSB_FIRST, 8, },
       0 },
+    { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_B8G8R8A8_UNORM,
+      { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32,
+        32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
+      0 },
+    { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_R8G8B8A8_UNORM,
+      { VA_FOURCC('R','G','B','A'), VA_LSB_FIRST, 32,
+        32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
+      0 },
 };
 
 static const i965_subpic_format_map_t *
 get_subpic_format(const VAImageFormat *va_format)
 {
     unsigned int i;
-    for (i = 0; i < sizeof(i965_subpic_formats_map)/sizeof(i965_subpic_formats_map[0]); i++) {
+    for (i = 0; i965_subpic_formats_map[i].type != 0; i++) {
         const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[i];
         if (m->va_format.fourcc == va_format->fourcc &&
             (m->type == I965_SURFACETYPE_RGBA ?
@@ -364,8 +388,10 @@
         surfaces[i] = surfaceID;
         obj_surface->status = VASurfaceReady;
         obj_surface->subpic = VA_INVALID_ID;
-        obj_surface->width = ALIGN(width, 16);
-        obj_surface->height = ALIGN(height, 16);
+        obj_surface->orig_width = width;
+        obj_surface->orig_height = height;
+        obj_surface->width = ALIGN(obj_surface->orig_width, 16);
+        obj_surface->height = ALIGN(obj_surface->orig_height, 16);
         obj_surface->size = SIZE_YUV420(obj_surface->width, obj_surface->height);
         obj_surface->flags = SURFACE_REFERENCED;
         obj_surface->bo = NULL;
@@ -411,8 +437,16 @@
                        VAImageFormat *format_list,      /* out */
                        int *num_formats)                /* out */
 {
+    int n;
+
+    for (n = 0; i965_image_formats_map[n].va_format.fourcc != 0; n++) {
+        const i965_image_format_map_t * const m = &i965_image_formats_map[n];
+        if (format_list)
+            format_list[n] = m->va_format;
+    }
+
     if (num_formats)
-        *num_formats = 0;
+        *num_formats = n;
 
     return VA_STATUS_SUCCESS;
 }
@@ -488,6 +522,7 @@
     obj_subpic->format = m->format;
     obj_subpic->width  = obj_image->image.width;
     obj_subpic->height = obj_image->image.height;
+    obj_subpic->pitch  = obj_image->image.pitches[0];
     obj_subpic->bo     = obj_image->bo;
     return VA_STATUS_SUCCESS;
 }
@@ -508,7 +543,8 @@
                         VASubpictureID subpicture,
                         VAImageID image)
 {
-    return VA_STATUS_SUCCESS;
+    /* TODO */
+    return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
 VAStatus 
@@ -518,7 +554,8 @@
                             unsigned int chromakey_max,
                             unsigned int chromakey_mask)
 {
-    return VA_STATUS_SUCCESS;
+    /* TODO */
+    return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
 VAStatus 
@@ -526,7 +563,8 @@
                               VASubpictureID subpicture,
                               float global_alpha)
 {
-    return VA_STATUS_SUCCESS;
+    /* TODO */
+    return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
 VAStatus 
@@ -661,6 +699,7 @@
                    VAContextID *context)                /* out */
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct i965_render_state *render_state = &i965->render_state;
     struct object_config *obj_config = CONFIG(config_id);
     struct object_context *obj_context = NULL;
     VAStatus vaStatus = VA_STATUS_SUCCESS;
@@ -682,6 +721,16 @@
         return vaStatus;
     }
 
+    switch (obj_config->profile) {
+    case VAProfileH264Baseline:
+    case VAProfileH264Main:
+    case VAProfileH264High:
+        render_state->interleaved_uv = 1;
+        break;
+    default:
+        render_state->interleaved_uv = 0;
+    }
+
     obj_context->context_id = contextID;
     *context = contextID;
     memset(&obj_context->decode_state, 0, sizeof(obj_context->decode_state));
@@ -1076,7 +1125,6 @@
 i965_EndPicture(VADriverContextP ctx, VAContextID context)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx); 
-    struct i965_render_state *render_state = &i965->render_state;
     struct object_context *obj_context = CONTEXT(context);
     struct object_config *obj_config;
     VAContextID config;
@@ -1092,17 +1140,6 @@
     obj_config = CONFIG(config);
     assert(obj_config);
 
-    switch (obj_config->profile) {
-    case VAProfileH264Baseline:
-    case VAProfileH264Main:
-    case VAProfileH264High:
-        render_state->interleaved_uv = 1;
-        break;
-
-    default:
-        render_state->interleaved_uv = 0;
-    }
-
     i965_media_decode_picture(ctx, obj_config->profile, &obj_context->decode_state);
     obj_context->decode_state.current_render_target = -1;
     obj_context->decode_state.num_slice_params = 0;
@@ -1175,7 +1212,7 @@
                           int num_attributes)
 {
     /* TODO */
-    return VA_STATUS_ERROR_UNKNOWN;
+    return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
 /* 
@@ -1190,7 +1227,7 @@
                           int num_attributes)
 {
     /* TODO */
-    return VA_STATUS_ERROR_UNKNOWN;
+    return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
 VAStatus 
@@ -1200,7 +1237,7 @@
                             unsigned int *stride)       /* out */
 {
     /* TODO */
-    return VA_STATUS_ERROR_UNKNOWN;
+    return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
 static VAStatus 
@@ -1299,6 +1336,43 @@
         image->component_order[1]  = 'G';
         image->component_order[2]  = 'B';
         break;
+    case VA_FOURCC('A','R','G','B'):
+    case VA_FOURCC('A','B','G','R'):
+    case VA_FOURCC('B','G','R','A'):
+    case VA_FOURCC('R','G','B','A'):
+        image->num_planes = 1;
+        image->pitches[0] = width * 4;
+        image->offsets[0] = 0;
+        image->data_size  = image->offsets[0] + image->pitches[0] * height;
+        break;
+    case VA_FOURCC('Y','V','1','2'):
+        image->num_planes = 3;
+        image->pitches[0] = width;
+        image->offsets[0] = 0;
+        image->pitches[1] = width2;
+        image->offsets[1] = size + size2;
+        image->pitches[2] = width2;
+        image->offsets[2] = size;
+        image->data_size  = size + 2 * size2;
+        break;
+    case VA_FOURCC('I','4','2','0'):
+        image->num_planes = 3;
+        image->pitches[0] = width;
+        image->offsets[0] = 0;
+        image->pitches[1] = width2;
+        image->offsets[1] = size;
+        image->pitches[2] = width2;
+        image->offsets[2] = size + size2;
+        image->data_size  = size + 2 * size2;
+        break;
+    case VA_FOURCC('N','V','1','2'):
+        image->num_planes = 2;
+        image->pitches[0] = width;
+        image->offsets[0] = 0;
+        image->pitches[1] = width;
+        image->offsets[1] = size;
+        image->data_size  = size + 2 * size2;
+        break;
     default:
         goto error;
     }
@@ -1333,7 +1407,8 @@
                           VASurfaceID surface,
                           VAImage *image)        /* out */
 {
-    return VA_STATUS_SUCCESS;
+    /* TODO */
+    return VA_STATUS_ERROR_OPERATION_FAILED;
 }
 
 static void 
@@ -1394,6 +1469,109 @@
     return VA_STATUS_SUCCESS;
 }
 
+static inline void
+memcpy_pic(uint8_t *dst, unsigned int dst_stride,
+           const uint8_t *src, unsigned int src_stride,
+           unsigned int len, unsigned int height)
+{
+    unsigned int i;
+
+    for (i = 0; i < height; i++) {
+        memcpy(dst, src, len);
+        dst += dst_stride;
+        src += src_stride;
+    }
+}
+
+static void
+get_image_i420(struct object_image *obj_image, uint8_t *image_data,
+               struct object_surface *obj_surface,
+               const VARectangle *rect)
+{
+    uint8_t *dst[3], *src[3];
+    const int Y = 0;
+    const int U = obj_image->image.format.fourcc == VA_FOURCC_YV12 ? 2 : 1;
+    const int V = obj_image->image.format.fourcc == VA_FOURCC_YV12 ? 1 : 2;
+
+    if (!obj_surface->bo)
+        return;
+
+    dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Dest VA image has either I420 or YV12 format.
+       Source VA surface alway has I420 format */
+    dst[Y] = image_data + obj_image->image.offsets[Y];
+    src[0] = (uint8_t *)obj_surface->bo->virtual;
+    dst[U] = image_data + obj_image->image.offsets[U];
+    src[1] = src[0] + obj_surface->width * obj_surface->height;
+    dst[V] = image_data + obj_image->image.offsets[V];
+    src[2] = src[1] + (obj_surface->width / 2) * (obj_surface->height / 2);
+
+    /* Y plane */
+    dst[Y] += rect->y * obj_image->image.pitches[Y] + rect->x;
+    src[0] += rect->y * obj_surface->width + rect->x;
+    memcpy_pic(dst[Y], obj_image->image.pitches[Y],
+               src[0], obj_surface->width,
+               rect->width, rect->height);
+
+    /* U plane */
+    dst[U] += (rect->y / 2) * obj_image->image.pitches[U] + rect->x / 2;
+    src[1] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2;
+    memcpy_pic(dst[U], obj_image->image.pitches[U],
+               src[1], obj_surface->width / 2,
+               rect->width / 2, rect->height / 2);
+
+    /* V plane */
+    dst[V] += (rect->y / 2) * obj_image->image.pitches[V] + rect->x / 2;
+    src[2] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2;
+    memcpy_pic(dst[V], obj_image->image.pitches[V],
+               src[2], obj_surface->width / 2,
+               rect->width / 2, rect->height / 2);
+
+    dri_bo_unmap(obj_surface->bo);
+}
+
+static void
+get_image_nv12(struct object_image *obj_image, uint8_t *image_data,
+               struct object_surface *obj_surface,
+               const VARectangle *rect)
+{
+    uint8_t *dst[2], *src[2];
+
+    if (!obj_surface->bo)
+        return;
+
+    dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Both dest VA image and source surface have NV12 format */
+    dst[0] = image_data + obj_image->image.offsets[0];
+    src[0] = (uint8_t *)obj_surface->bo->virtual;
+    dst[1] = image_data + obj_image->image.offsets[1];
+    src[1] = src[0] + obj_surface->width * obj_surface->height;
+
+    /* Y plane */
+    dst[0] += rect->y * obj_image->image.pitches[0] + rect->x;
+    src[0] += rect->y * obj_surface->width + rect->x;
+    memcpy_pic(dst[0], obj_image->image.pitches[0],
+               src[0], obj_surface->width,
+               rect->width, rect->height);
+
+    /* UV plane */
+    dst[1] += (rect->y / 2) * obj_image->image.pitches[1] + (rect->x & -2);
+    src[1] += (rect->y / 2) * obj_surface->width + (rect->x & -2);
+    memcpy_pic(dst[1], obj_image->image.pitches[1],
+               src[1], obj_surface->width,
+               rect->width, rect->height / 2);
+
+    dri_bo_unmap(obj_surface->bo);
+}
+
 VAStatus 
 i965_GetImage(VADriverContextP ctx,
               VASurfaceID surface,
@@ -1403,7 +1581,64 @@
               unsigned int height,
               VAImageID image)
 {
-    return VA_STATUS_SUCCESS;
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct i965_render_state *render_state = &i965->render_state;
+
+    struct object_surface *obj_surface = SURFACE(surface);
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    struct object_image *obj_image = IMAGE(image);
+    if (!obj_image)
+        return VA_STATUS_ERROR_INVALID_IMAGE;
+
+    if (x < 0 || y < 0)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (x + width > obj_surface->orig_width ||
+        y + height > obj_surface->orig_height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (x + width > obj_image->image.width ||
+        y + height > obj_image->image.height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    /* Commit pending operations to the HW */
+    intel_batchbuffer_flush(ctx);
+
+    VAStatus va_status;
+    void *image_data = NULL;
+
+    va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    VARectangle rect;
+    rect.x = x;
+    rect.y = y;
+    rect.width = width;
+    rect.height = height;
+
+    switch (obj_image->image.format.fourcc) {
+    case VA_FOURCC('Y','V','1','2'):
+    case VA_FOURCC('I','4','2','0'):
+        /* I420 is native format for MPEG-2 decoded surfaces */
+        if (render_state->interleaved_uv)
+            goto operation_failed;
+        get_image_i420(obj_image, image_data, obj_surface, &rect);
+        break;
+    case VA_FOURCC('N','V','1','2'):
+        /* NV12 is native format for H.264 decoded surfaces */
+        if (!render_state->interleaved_uv)
+            goto operation_failed;
+        get_image_nv12(obj_image, image_data, obj_surface, &rect);
+        break;
+    default:
+    operation_failed:
+        va_status = VA_STATUS_ERROR_OPERATION_FAILED;
+        break;
+    }
+
+    i965_UnmapBuffer(ctx, obj_image->image.buf);
+    return va_status;
 }
 
 VAStatus 
diff --git a/i965_drv_video/i965_drv_video.h b/i965_drv_video/i965_drv_video.h
index b4a1576..8643bd6 100644
--- a/i965_drv_video/i965_drv_video.h
+++ b/i965_drv_video/i965_drv_video.h
@@ -43,8 +43,8 @@
 #define I965_MAX_PROFILES                       11
 #define I965_MAX_ENTRYPOINTS                    5
 #define I965_MAX_CONFIG_ATTRIBUTES              10
-#define I965_MAX_IMAGE_FORMATS                  10
-#define I965_MAX_SUBPIC_FORMATS                 2
+#define I965_MAX_IMAGE_FORMATS                  3
+#define I965_MAX_SUBPIC_FORMATS                 4
 #define I965_MAX_DISPLAY_ATTRIBUTES             4
 #define I965_STR_VENDOR                         "i965 Driver 0.1"
 
@@ -105,6 +105,8 @@
     int width;
     int height;
     int size;
+    int orig_width;
+    int orig_height;
     int flags;
     dri_bo *bo;
     void (*free_private_data)(void **data);
@@ -138,6 +140,7 @@
     unsigned int format;
     int width;
     int height;
+    int pitch;
     dri_bo *bo;
 };
 
diff --git a/i965_drv_video/i965_media.c b/i965_drv_video/i965_media.c
index 31a8fbe..8945444 100644
--- a/i965_drv_video/i965_media.c
+++ b/i965_drv_video/i965_media.c
@@ -292,8 +292,8 @@
     struct i965_media_state *media_state = &i965->media_state;
     int i;
 
-    assert(media_state->free_private_context);
-    media_state->free_private_context(&media_state->private_context);
+    if (media_state->free_private_context)
+        media_state->free_private_context(&media_state->private_context);
 
     for (i = 0; i < MAX_MEDIA_SURFACES; i++) {
         dri_bo_unreference(media_state->surface_state[i].bo);
diff --git a/i965_drv_video/i965_render.c b/i965_drv_video/i965_render.c
index 720bb53..c4e8ed8 100644
--- a/i965_drv_video/i965_render.c
+++ b/i965_drv_video/i965_render.c
@@ -592,7 +592,7 @@
                               int index,
                               dri_bo *region,
                               unsigned long offset,
-                              int w, int h, int format)
+                              int w, int h, int p, int format)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);  
     struct i965_render_state *render_state = &i965->render_state;
@@ -626,7 +626,7 @@
     ss->ss2.mip_count = 0;
     ss->ss2.render_target_rotation = 0;
 
-    ss->ss3.pitch = w - 1;
+    ss->ss3.pitch = p - 1;
 
     dri_bo_emit_reloc(ss_bo,
                       I915_GEM_DOMAIN_SAMPLER, 0,
@@ -650,6 +650,7 @@
     struct i965_render_state *render_state = &i965->render_state;
     struct object_surface *obj_surface;
     int w, h;
+    int rw, rh;
     dri_bo *region;
 
     obj_surface = SURFACE(surface);
@@ -657,19 +658,21 @@
     assert(obj_surface->bo);
     w = obj_surface->width;
     h = obj_surface->height;
+    rw = obj_surface->orig_width;
+    rh = obj_surface->orig_height;
     region = obj_surface->bo;
 
-    i965_render_src_surface_state(ctx, 1, region, 0, w, h, w, I965_SURFACEFORMAT_R8_UNORM);     /* Y */
-    i965_render_src_surface_state(ctx, 2, region, 0, w, h, w, I965_SURFACEFORMAT_R8_UNORM);
+    i965_render_src_surface_state(ctx, 1, region, 0, rw, rh, w, I965_SURFACEFORMAT_R8_UNORM);     /* Y */
+    i965_render_src_surface_state(ctx, 2, region, 0, rw, rh, w, I965_SURFACEFORMAT_R8_UNORM);
 
     if (render_state->interleaved_uv) {
-        i965_render_src_surface_state(ctx, 3, region, w * h, w / 2, h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM); /* UV */
-        i965_render_src_surface_state(ctx, 4, region, w * h, w / 2, h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM);
+        i965_render_src_surface_state(ctx, 3, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8G8_UNORM); /* UV */
+        i965_render_src_surface_state(ctx, 4, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8G8_UNORM);
     } else {
-        i965_render_src_surface_state(ctx, 3, region, w * h, w / 2, h / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM); /* U */
-        i965_render_src_surface_state(ctx, 4, region, w * h, w / 2, h / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
-        i965_render_src_surface_state(ctx, 5, region, w * h + w * h / 4, w / 2, h / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);     /* V */
-        i965_render_src_surface_state(ctx, 6, region, w * h + w * h / 4, w / 2, h / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
+        i965_render_src_surface_state(ctx, 3, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM); /* U */
+        i965_render_src_surface_state(ctx, 4, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
+        i965_render_src_surface_state(ctx, 5, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);     /* V */
+        i965_render_src_surface_state(ctx, 6, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
     }
 }
 
@@ -691,8 +694,8 @@
     region = obj_surface->bo;
     subpic_region = obj_image->bo;
     /*subpicture surface*/
-    i965_subpic_render_src_surface_state(ctx, 1, subpic_region, 0, obj_subpic->width, obj_subpic->height, obj_subpic->format);     
-    i965_subpic_render_src_surface_state(ctx, 2, subpic_region, 0, obj_subpic->width, obj_subpic->height, obj_subpic->format);     
+    i965_subpic_render_src_surface_state(ctx, 1, subpic_region, 0, obj_subpic->width, obj_subpic->height, obj_subpic->pitch, obj_subpic->format);     
+    i965_subpic_render_src_surface_state(ctx, 2, subpic_region, 0, obj_subpic->width, obj_subpic->height, obj_subpic->pitch, obj_subpic->format);     
 }
 
 static void
@@ -810,12 +813,8 @@
     struct object_surface    *obj_surface  = SURFACE(surface);
     struct object_subpic     *obj_subpic   = SUBPIC(obj_surface->subpic);
 
-    const float psx = (float)obj_surface->width  / (float)obj_subpic->width;
-    const float psy = (float)obj_surface->height / (float)obj_subpic->height;
-    const float ssx = (float)output_rect->width  / (float)obj_surface->width;
-    const float ssy = (float)output_rect->height / (float)obj_surface->height;
-    const float sx  = psx * ssx;
-    const float sy  = psy * ssy;
+    const float sx = (float)output_rect->width  / (float)obj_surface->orig_width;
+    const float sy = (float)output_rect->height / (float)obj_surface->orig_height;
     float *vb, tx1, tx2, ty1, ty2, x1, x2, y1, y2;
     int i = 0;
 
@@ -883,8 +882,8 @@
 
     obj_surface = SURFACE(surface);
     assert(surface);
-    width = obj_surface->width;
-    height = obj_surface->height;
+    width = obj_surface->orig_width;
+    height = obj_surface->orig_height;
 
     u1 = (float)srcx / width;
     v1 = (float)srcy / height;
diff --git a/va/Makefile.am b/va/Makefile.am
index 2ff3a23..8451a38 100644
--- a/va/Makefile.am
+++ b/va/Makefile.am
@@ -43,7 +43,7 @@
 libva_x11_backenddir   = x11
 
 libva_x11_la_SOURCES = 
-libva_x11_la_LIBADD  = $(libvacorelib) x11/libva_x11.la $(LIBVA_LIBS) $(X11_LIBS) $(XEXT_LIBS) $(DRM_LIBS) $(XFIXES_LIBS)
+libva_x11_la_LIBADD  = $(libvacorelib) x11/libva_x11.la $(LIBVA_LIBS) $(X11_LIBS) $(XEXT_LIBS) $(DRM_LIBS) $(XFIXES_LIBS) -ldl
 libva_x11_la_LDFLAGS = $(LDADD)
 libva_x11_la_DEPENDENCIES = $(libvacorelib) x11/libva_x11.la
 
diff --git a/va/va.c b/va/va.c
index e143c7b..c0722ba 100644
--- a/va/va.c
+++ b/va/va.c
@@ -25,6 +25,7 @@
 #define _GNU_SOURCE 1
 #include "va.h"
 #include "va_backend.h"
+#include "va_trace.h"
 #include "config.h"
 
 #include <assert.h>
diff --git a/va/va.h b/va/va.h
index e350f74..76c5708 100644
--- a/va/va.h
+++ b/va/va.h
@@ -1721,6 +1721,9 @@
      * then the value for this attribute will be set to 1 so that the client   
      * will not attempt to re-use the surface right after returning from a call
      * to PutSurface.
+     *
+     * Don't use it, use flag VASurfaceDisplaying of vaQuerySurfaceStatus since
+     * driver may use overlay or GPU alternatively
      */
     VADisplayAttribDirectSurface       = 5,
     VADisplayAttribRotation            = 6,	
@@ -1731,11 +1734,11 @@
     VADisplayAttribBLEWhiteMode        = 9,
     VADisplayAttribBlueStretch         = 10,
     VADisplayAttribSkinColorCorrection = 11,
-    VADisplayAttribCSCInputColorFormat = 12,
-    VADisplayAttribCSCHue              = 13,
-    VADisplayAttribCSCSaturation       = 14,
-    VADisplayAttribCSCBrightness       = 15,
-    VADisplayAttribCSCContrast         = 16,
+    /*
+     * For type VADisplayAttribCSCMatrix, "value" field is a pointer to the color
+     * conversion matrix. Each element in the matrix is float-point
+     */
+    VADisplayAttribCSCMatrix           = 12
 } VADisplayAttribType;
 
 /* flags for VADisplayAttribute */
diff --git a/va/va_trace.c b/va/va_trace.c
index 1713f27..4ec9195 100644
--- a/va/va_trace.c
+++ b/va/va_trace.c
@@ -25,6 +25,7 @@
 #define _GNU_SOURCE 1
 #include "va.h"
 #include "va_backend.h"
+#include "va_trace.h"
 
 #include <assert.h>
 #include <stdarg.h>
@@ -48,7 +49,34 @@
 static unsigned int trace_width;
 static unsigned int trace_height;
 
-int va_TraceInit(void)
+/* Prototypes (functions defined in va.c) */
+VAStatus vaBufferInfo (
+    VADisplay dpy,
+    VAContextID context,	/* in */
+    VABufferID buf_id,		/* in */
+    VABufferType *type,		/* out */
+    unsigned int *size,		/* out */
+    unsigned int *num_elements	/* out */
+);
+
+VAStatus vaLockSurface(VADisplay dpy,
+    VASurfaceID surface,
+    unsigned int *fourcc, /* following are output argument */
+    unsigned int *luma_stride,
+    unsigned int *chroma_u_stride,
+    unsigned int *chroma_v_stride,
+    unsigned int *luma_offset,
+    unsigned int *chroma_u_offset,
+    unsigned int *chroma_v_offset,
+    unsigned int *buffer_name,
+    void **buffer 
+);
+
+VAStatus vaUnlockSurface(VADisplay dpy,
+    VASurfaceID surface
+);
+
+void va_TraceInit(void)
 {
     trace_file = (const char *)getenv("LIBVA_TRACE");
     if (trace_file) {
@@ -58,7 +86,7 @@
     }
 }
 
-int va_TraceEnd(void)
+void va_TraceEnd(void)
 {
     if (trace_file && trace_fp) {
         fclose(trace_fp);
@@ -73,7 +101,7 @@
     }
 }
 
-int va_TraceMsg(const char *msg, ...)
+void va_TraceMsg(const char *msg, ...)
 {
     va_list args;
     
@@ -87,7 +115,7 @@
 }
 
 
-int va_TraceCreateConfig(
+void va_TraceCreateConfig(
     VADisplay dpy,
     VAProfile profile, 
     VAEntrypoint entrypoint, 
@@ -110,7 +138,7 @@
 }
 
 
-int va_TraceCreateSurface(
+void va_TraceCreateSurface(
     VADisplay dpy,
     int width,
     int height,
@@ -131,7 +159,7 @@
 }
 
 
-int va_TraceCreateContext(
+void va_TraceCreateContext(
     VADisplay dpy,
     VAConfigID config_id,
     int picture_width,
@@ -721,7 +749,7 @@
     va_TraceMsg ("    slice_vertical_position       = %d\n", p->slice_vertical_position);
 }
 
-int va_TraceBeginPicture(
+void va_TraceBeginPicture(
     VADisplay dpy,
     VAContextID context,
     VASurfaceID render_target
@@ -738,16 +766,7 @@
     trace_slice = 0;
 }
 
-VAStatus vaBufferInfo (
-    VADisplay dpy,
-    VAContextID context,	/* in */
-    VABufferID buf_id,		/* in */
-    VABufferType *type,		/* out */
-    unsigned int *size,		/* out */
-    unsigned int *num_elements	/* out */
-);
-
-static int va_TraceMPEG2Buf(
+static void va_TraceMPEG2Buf(
     VADisplay dpy,
     VAContextID context,
     VABufferID buffer,
@@ -798,12 +817,9 @@
     case VAEncH264SEIBufferType:
         break;
     }
-    
-    return 0;
 }
 
-
-static int va_TraceMPEG4Buf(
+static void va_TraceMPEG4Buf(
     VADisplay dpy,
     VAContextID context,
     VABufferID buffer,
@@ -856,13 +872,10 @@
     default:
         break;
     }
-    
-    
-    return 0;
 }
 
 
-static int va_TraceH264Buf(
+static void va_TraceH264Buf(
     VADisplay dpy,
     VAContextID context,
     VABufferID buffer,
@@ -874,7 +887,7 @@
 {
     switch (type) {
     case VAPictureParameterBufferType:
-        va_TraceVAPictureParameterBufferMPEG2(dpy, context, buffer, type, size, num_elements, pbuf);
+        va_TraceVAPictureParameterBufferH264(dpy, context, buffer, type, size, num_elements, pbuf);
         break;
     case VAIQMatrixBufferType:
         va_TraceVAIQMatrixBufferH264(dpy, context, buffer, type, size, num_elements, pbuf);
@@ -915,13 +928,10 @@
     default:
         break;
     }
-    
-    
-    return 0;
 }
 
 
-static int va_TraceVC1Buf(
+static void va_TraceVC1Buf(
     VADisplay dpy,
     VAContextID context,
     VABufferID buffer,
@@ -974,11 +984,9 @@
     default:
         break;
     }
-    
-    return 0;
 }
 
-int va_TraceRenderPicture(
+void va_TraceRenderPicture(
     VADisplay dpy,
     VAContextID context,
     VABufferID *buffers,
@@ -1035,7 +1043,7 @@
 }
 
 
-int va_TraceEndPicture(
+void va_TraceEndPicture(
     VADisplay dpy,
     VAContextID context
 )
@@ -1066,7 +1074,7 @@
                                       &luma_offset, &chroma_u_offset, &chroma_v_offset, &buffer_name, &buffer);
 
     if (va_status != VA_STATUS_SUCCESS)
-        return va_status;
+        return;
     
     va_TraceMsg("\tfourcc=0x%08x\n", fourcc);
     va_TraceMsg("\twidth=%d\n", trace_width);
@@ -1078,8 +1086,10 @@
     va_TraceMsg("\tchroma_u_offset=%d\n", chroma_u_offset);
     va_TraceMsg("\tchroma_v_offset=%d\n", chroma_v_offset);
 
-    if (!buffer)
+    if (!buffer) {
+        vaUnlockSurface(dpy, trace_rendertarget);
         return;
+    }
 
     Y_data = buffer;
     UV_data = buffer + luma_offset;
@@ -1112,4 +1122,6 @@
             tmp = UV_data + i * chroma_u_stride;
         }
     }
+
+    vaUnlockSurface(dpy, trace_rendertarget);
 }
diff --git a/va/va_trace.h b/va/va_trace.h
new file mode 100644
index 0000000..1c860e3
--- /dev/null
+++ b/va/va_trace.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VA_TRACE_H
+#define VA_TRACE_H
+
+void va_TraceInit(void);
+void va_TraceEnd(void);
+
+void va_TraceMsg(const char *msg, ...);
+
+void va_TraceCreateConfig(
+    VADisplay dpy,
+    VAProfile profile, 
+    VAEntrypoint entrypoint, 
+    VAConfigAttrib *attrib_list,
+    int num_attribs,
+    VAConfigID *config_id /* out */
+);
+
+void va_TraceCreateSurface(
+    VADisplay dpy,
+    int width,
+    int height,
+    int format,
+    int num_surfaces,
+    VASurfaceID *surfaces	/* out */
+);
+
+void va_TraceCreateContext(
+    VADisplay dpy,
+    VAConfigID config_id,
+    int picture_width,
+    int picture_height,
+    int flag,
+    VASurfaceID *render_targets,
+    int num_render_targets,
+    VAContextID *context		/* out */
+);
+
+void va_TraceBeginPicture(
+    VADisplay dpy,
+    VAContextID context,
+    VASurfaceID render_target
+);
+
+void va_TraceRenderPicture(
+    VADisplay dpy,
+    VAContextID context,
+    VABufferID *buffers,
+    int num_buffers
+);
+
+void va_TraceEndPicture(
+    VADisplay dpy,
+    VAContextID context
+);
+
+#endif /* VA_TRACE_H */
diff --git a/va/x11/Makefile.am b/va/x11/Makefile.am
index 40346f1..2e3619c 100644
--- a/va/x11/Makefile.am
+++ b/va/x11/Makefile.am
@@ -25,6 +25,6 @@
 libva_x11includedir = ${includedir}/va
 libva_x11include_HEADERS = va_dri.h va_dri2.h va_dricommon.h
 
-libva_x11_la_SOURCES = va_x11.c va_dri.c va_dri2.c va_dricommon.c dri2_util.c dri1_util.c va_nvctrl.c
+libva_x11_la_SOURCES = va_x11.c va_dri.c va_dri2.c va_dricommon.c dri2_util.c dri1_util.c va_nvctrl.c va_fglrx.c
 
-EXTRA_DIST = va_dristr.h va_dri2str.h va_dri2tokens.h va_nvctrl.h
+EXTRA_DIST = va_dristr.h va_dri2str.h va_dri2tokens.h va_nvctrl.h va_fglrx.h
diff --git a/va/x11/va_fglrx.c b/va/x11/va_fglrx.c
new file mode 100644
index 0000000..5be0256
--- /dev/null
+++ b/va/x11/va_fglrx.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2010 Splitted-Desktop Systems. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <X11/Xlib.h>
+
+#define ADL_OK 0
+#define ADL_MAX_PATH 256
+
+/*
+ * Based on public AMD Display Library (ADL) SDK:
+ * <http://developer.amd.com/gpu/adlsdk/Pages/default.aspx>
+ */
+typedef struct AdapterInfo {
+    int iSize;
+    int iAdapterIndex;
+    char strUDID[ADL_MAX_PATH]; 
+    int iBusNumber;
+    int iDeviceNumber;
+    int iFunctionNumber;
+    int iVendorID;
+    char strAdapterName[ADL_MAX_PATH];
+    char strDisplayName[ADL_MAX_PATH];
+    int iPresent;
+    int iXScreenNum;
+    int iDrvIndex;
+    char strXScreenConfigName[ADL_MAX_PATH];
+} AdapterInfo, *LPAdapterInfo;
+
+typedef struct XScreenInfo {
+    int iXScreenNum;
+    char strXScreenConfigName[ADL_MAX_PATH];
+} XScreenInfo, *LPXScreenInfo;
+
+typedef void *(*ADL_MAIN_MALLOC_CALLBACK)(int);
+typedef int (*ADL_MAIN_CONTROL_CREATE)(ADL_MAIN_MALLOC_CALLBACK, int);
+typedef int (*ADL_MAIN_CONTROL_DESTROY)(void);
+typedef int (*ADL_ADAPTER_NUMBEROFADAPTERS_GET)(int *);
+typedef int (*ADL_ADAPTER_ADAPTERINFO_GET)(LPAdapterInfo, int);
+typedef int (*ADL_ADAPTER_XSCREENINFO_GET)(LPXScreenInfo, int);
+
+static void *ADL_Main_Memory_Alloc(int iSize)
+{
+    return malloc(iSize);
+}
+
+static void ADL_Main_Memory_Free(void *arg)
+{
+    void ** const lpBuffer = arg;
+
+    if (lpBuffer && *lpBuffer) {
+        free(*lpBuffer);
+        *lpBuffer = NULL;
+    }
+}
+
+static int match_display(Display *x11_dpy, const char *display_name)
+{
+    Display *test_dpy;
+    char *test_dpy_name, *x11_dpy_name;
+    int m;
+
+    test_dpy = XOpenDisplay(display_name);
+    if (!test_dpy)
+        return 0;
+
+    test_dpy_name = XDisplayString(test_dpy);
+    x11_dpy_name  = XDisplayString(x11_dpy);
+
+    if (x11_dpy_name && test_dpy_name)
+        m = strcmp(x11_dpy_name, test_dpy_name) == 0;
+    else
+        m = !x11_dpy_name && !test_dpy_name;
+
+    XCloseDisplay(test_dpy);
+    return m;
+}
+
+Bool VA_FGLRXGetClientDriverName( Display *dpy, int screen,
+    int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+    int *ddxDriverPatchVersion, char **clientDriverName )
+{
+    ADL_MAIN_CONTROL_CREATE          ADL_Main_Control_Create;
+    ADL_MAIN_CONTROL_DESTROY         ADL_Main_Control_Destroy;
+    ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get;
+    ADL_ADAPTER_ADAPTERINFO_GET      ADL_Adapter_AdapterInfo_Get;
+    ADL_ADAPTER_XSCREENINFO_GET      ADL_Adapter_XScreenInfo_Get;
+
+    LPAdapterInfo lpAdapterInfo = NULL;
+    LPXScreenInfo lpXScreenInfo = NULL;
+    void *libadl_handle = NULL;
+    Bool success = False;
+    int is_adl_initialized = 0;
+    int i, num_adapters, lpAdapterInfo_size, lpXScreenInfo_size;
+
+    if (ddxDriverMajorVersion)
+        *ddxDriverMajorVersion = 0;
+    if (ddxDriverMinorVersion)
+        *ddxDriverMinorVersion = 0;
+    if (ddxDriverPatchVersion)
+        *ddxDriverPatchVersion = 0;
+    if (clientDriverName)
+        *clientDriverName = NULL;
+
+    libadl_handle = dlopen("libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL);
+    if (!libadl_handle)
+        goto end;
+
+    dlerror();
+    ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE)
+        dlsym(libadl_handle,"ADL_Main_Control_Create");
+    if (dlerror())
+        goto end;
+
+    ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY)
+        dlsym(libadl_handle,"ADL_Main_Control_Destroy");
+    if (dlerror())
+        goto end;
+
+    ADL_Adapter_NumberOfAdapters_Get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET)
+        dlsym(libadl_handle,"ADL_Adapter_NumberOfAdapters_Get");
+    if (dlerror())
+        goto end;
+
+    ADL_Adapter_AdapterInfo_Get = (ADL_ADAPTER_ADAPTERINFO_GET)
+        dlsym(libadl_handle,"ADL_Adapter_AdapterInfo_Get");
+    if (dlerror())
+        goto end;
+
+    ADL_Adapter_XScreenInfo_Get = (ADL_ADAPTER_XSCREENINFO_GET)
+        dlsym(libadl_handle,"ADL_Adapter_XScreenInfo_Get");
+    if (dlerror())
+        goto end;
+
+    if (ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1) != ADL_OK)
+        goto end;
+    is_adl_initialized = 1;
+
+    if (ADL_Adapter_NumberOfAdapters_Get(&num_adapters) != ADL_OK)
+        goto end;
+    if (num_adapters <= 0)
+        goto end;
+
+    lpAdapterInfo_size = num_adapters * sizeof(*lpAdapterInfo);
+    lpAdapterInfo = ADL_Main_Memory_Alloc(lpAdapterInfo_size);
+    if (!lpAdapterInfo)
+        goto end;
+    memset(lpAdapterInfo, 0, lpAdapterInfo_size);
+
+    for (i = 0; i < num_adapters; i++)
+        lpAdapterInfo[i].iSize = sizeof(lpAdapterInfo[i]);
+
+    lpXScreenInfo_size = num_adapters * sizeof(*lpXScreenInfo);
+    lpXScreenInfo = ADL_Main_Memory_Alloc(lpXScreenInfo_size);
+    if (!lpXScreenInfo)
+        goto end;
+    memset(lpXScreenInfo, 0, lpXScreenInfo_size);
+
+    if (ADL_Adapter_AdapterInfo_Get(lpAdapterInfo, lpAdapterInfo_size) != ADL_OK)
+        goto end;
+
+    if (ADL_Adapter_XScreenInfo_Get(lpXScreenInfo, lpXScreenInfo_size) != ADL_OK)
+        goto end;
+
+    for (i = 0; i < num_adapters; i++) {
+        LPXScreenInfo const lpCurrXScreenInfo = &lpXScreenInfo[i];
+        LPAdapterInfo const lpCurrAdapterInfo = &lpAdapterInfo[i];
+        if (!lpCurrAdapterInfo->iPresent)
+            continue;
+#if 0
+        printf("Adapter %d:\n", i);
+        printf("  iAdapterIndex: %d\n",    lpCurrAdapterInfo->iAdapterIndex);
+        printf("  strUDID: '%s'\n",        lpCurrAdapterInfo->strUDID);
+        printf("  iBusNumber: %d\n",       lpCurrAdapterInfo->iBusNumber);
+        printf("  iDeviceNumber: %d\n",    lpCurrAdapterInfo->iDeviceNumber);
+        printf("  iFunctionNumber: %d\n",  lpCurrAdapterInfo->iFunctionNumber);
+        printf("  iVendorID: 0x%04x\n",    lpCurrAdapterInfo->iVendorID);
+        printf("  strAdapterName: '%s'\n", lpCurrAdapterInfo->strAdapterName);
+        printf("  strDisplayName: '%s'\n", lpCurrAdapterInfo->strDisplayName);
+        printf("  iPresent: %d\n",         lpCurrAdapterInfo->iPresent);
+        printf("  iXScreenNum: %d\n",      lpCurrXScreenInfo->iXScreenNum);
+#endif
+        if (match_display(dpy, lpCurrAdapterInfo->strDisplayName) &&
+            screen == lpCurrXScreenInfo->iXScreenNum) {
+            *clientDriverName = strdup("fglrx");
+            break;
+        }
+    }
+
+    success = True;
+end:
+    if (lpXScreenInfo)
+        ADL_Main_Memory_Free(&lpXScreenInfo);
+    if (lpAdapterInfo)
+        ADL_Main_Memory_Free(&lpAdapterInfo);
+    if (is_adl_initialized)
+        ADL_Main_Control_Destroy();
+    if (libadl_handle)
+        dlclose(libadl_handle);
+    return success;
+}
diff --git a/va/x11/va_fglrx.h b/va/x11/va_fglrx.h
new file mode 100644
index 0000000..6616044
--- /dev/null
+++ b/va/x11/va_fglrx.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Splitted-Desktop Systems. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VA_FGLRX_H
+#define VA_FGLRX_H
+
+#include <X11/Xlib.h>
+
+Bool VA_FGLRXGetClientDriverName( Display *dpy, int screen,
+    int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+    int *ddxDriverPatchVersion, char **clientDriverName );
+
+#endif /* VA_FGLRX_H */
diff --git a/va/x11/va_x11.c b/va/x11/va_x11.c
index 7f8fbd6..cbd2614 100644
--- a/va/x11/va_x11.c
+++ b/va/x11/va_x11.c
@@ -31,6 +31,7 @@
 #include "va_dri2.h"
 #include "va_dricommon.h"
 #include "va_nvctrl.h"
+#include "va_fglrx.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -130,6 +131,24 @@
     return VA_STATUS_SUCCESS;
 }
 
+static VAStatus va_FGLRX_GetDriverName (
+    VADisplayContextP pDisplayContext,
+    char **driver_name
+)
+{
+    VADriverContextP ctx = pDisplayContext->pDriverContext;
+    int driver_major, driver_minor, driver_patch;
+    Bool result;
+
+    result = VA_FGLRXGetClientDriverName(ctx->native_dpy, ctx->x11_screen,
+                                         &driver_major, &driver_minor,
+                                         &driver_patch, driver_name);
+    if (!result)
+        return VA_STATUS_ERROR_UNKNOWN;
+
+    return VA_STATUS_SUCCESS;
+}
+
 static VAStatus va_DisplayContextGetDriverName (
     VADisplayContextP pDisplayContext,
     char **driver_name
@@ -145,7 +164,8 @@
         vaStatus = va_DRIGetDriverName(pDisplayContext, driver_name);
     if (vaStatus != VA_STATUS_SUCCESS)
         vaStatus = va_NVCTRL_GetDriverName(pDisplayContext, driver_name);
-   
+    if (vaStatus != VA_STATUS_SUCCESS)
+        vaStatus = va_FGLRX_GetDriverName(pDisplayContext, driver_name);
     return vaStatus;
 }