Hello.

I don't have a patch, as I can't still make it run on VMWare.
But tests on other graphic card can be good.
I have attached the file.

There is no Cairo code, no page_flip and
I have also added drmModeDirtyFB, as Jakob from vmware suggested to make it work under vmwgfx.

Regards.

----- Original Message ----- From: "Kristian Høgsberg" <k...@bitplanet.net>
To: "Peter Hanzel" <hanzelpe...@gmail.com>
Cc: <dri-devel@lists.sourceforge.net>
Sent: Tuesday, February 09, 2010 3:14 PM
Subject: Re: vmwgfx + VMWare 7.0 -> libdrm modetest.c


On Tue, Feb 9, 2010 at 8:05 AM, Peter Hanzel <hanzelpe...@gmail.com> wrote:
Hello.

I have a question about libdrm/libkms and test/modetest/modetest.c.
I am now working with vmwgfx + VMWare 7.0, where vmwgfx had correctly
initialized framebuffer and also now using fbcon.
Now I want to test it woth modetest.c
This program is only for intel so i recoded it to use libkms functions.

Could you send the changes to make modetest.c use libkms as a patch?
It's a good idea.

cheers,
Kristian

/*
* DRM based mode setting test program
* Copyright 2008 Tungsten Graphics
*   Jakob Bornecrantz <ja...@tungstengraphics.com>
* Copyright 2008 Intel Corporation
*   Jesse Barnes <jesse.bar...@intel.com>
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS 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.
*/

/*
* This fairly simple test program dumps output in a similar format to the
* "xrandr" tool everyone knows & loves.  It's necessarily slightly different
* since the kernel separates outputs into encoder and connector structures,
* each with their own unique ID.  The program also allows test testing of the
* memory management and mode setting APIs by allowing the user to specify a
* connector and mode to use for mode setting.  If all works as expected, a
* blue background should be painted on the monitor attached to the specified
* connector after the selected mode is set.
*
* TODO: use cairo to write the mode info on the selected output once
*       the mode has been programmed, along with possible test patterns.
*/
#include "config.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/poll.h>

#include "xf86drm.h"
#include "xf86drmMode.h"
#include "libkms/libkms.h"

struct kms_bo
{
       struct kms_driver *kms;
       void *ptr;
       size_t size;
       size_t offset;
       size_t pitch;
       unsigned handle;
};


drmModeRes *resources;
int fd, modes;

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

struct type_name {
        int type;
        char *name;
};

#define type_name_fn(res) \
char * res##_str(int type) {                    \
        int i;                                          \
        for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
                if (res##_names[i].type == type)        \
                        return res##_names[i].name;     \
        }                                               \
        return "(invalid)";                           \
}

struct type_name encoder_type_names[] = {
        { DRM_MODE_ENCODER_NONE, "none" },
        { DRM_MODE_ENCODER_DAC, "DAC" },
        { DRM_MODE_ENCODER_TMDS, "TMDS" },
        { DRM_MODE_ENCODER_LVDS, "LVDS" },
        { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
};

type_name_fn(encoder_type)

struct type_name connector_status_names[] = {
        { DRM_MODE_CONNECTED, "connected" },
        { DRM_MODE_DISCONNECTED, "disconnected" },
        { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
};

type_name_fn(connector_status)

struct type_name connector_type_names[] = {
        { DRM_MODE_CONNECTOR_Unknown, "unknown" },
        { DRM_MODE_CONNECTOR_VGA, "VGA" },
        { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
        { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
        { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
        { DRM_MODE_CONNECTOR_Composite, "composite" },
        { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
        { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
        { DRM_MODE_CONNECTOR_Component, "component" },
        { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
        { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
        { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
        { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
};

type_name_fn(connector_type)

void dump_encoders(void)
{
        drmModeEncoder *encoder;
        int i;

        printf("Encoders:\n");
        printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
        for (i = 0; i < resources->count_encoders; i++) {
                encoder = drmModeGetEncoder(fd, resources->encoders[i]);

                if (!encoder) {
                        fprintf(stderr, "could not get encoder %i: %s\n",
                                resources->encoders[i], strerror(errno));
                        continue;
                }
                printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
                       encoder->encoder_id,
                       encoder->crtc_id,
                       encoder_type_str(encoder->encoder_type),
                       encoder->possible_crtcs,
                       encoder->possible_clones);
                drmModeFreeEncoder(encoder);
        }
        printf("\n");
}

void dump_mode(drmModeModeInfo *mode)
{
        printf("  %s %.02f %d %d %d %d %d %d %d %d\n",
               mode->name,
               (float)mode->vrefresh / 1000,
               mode->hdisplay,
               mode->hsync_start,
               mode->hsync_end,
               mode->htotal,
               mode->vdisplay,
               mode->vsync_start,
               mode->vsync_end,
               mode->vtotal);
}

static void
dump_props(drmModeConnector *connector)
{
        drmModePropertyPtr props;
        int i;

        for (i = 0; i < connector->count_props; i++) {
                props = drmModeGetProperty(fd, connector->props[i]);
                //printf("\t%s, flags %d\n", props->name, props->flags);
                drmModeFreeProperty(props);
        }
}

void dump_connectors(void)
{
        drmModeConnector *connector;
        int i, j;

        printf("Connectors:\n");
        printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n");
        for (i = 0; i < resources->count_connectors; i++) {
                connector = drmModeGetConnector(fd, resources->connectors[i]);

                if (!connector) {
                        fprintf(stderr, "could not get connector %i: %s\n",
                                resources->connectors[i], strerror(errno));
                        continue;
                }

                printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t",
                       connector->connector_id,
                       connector->encoder_id,
                       connector_status_str(connector->connection),
                       connector_type_str(connector->connector_type),
                       connector->mmWidth, connector->mmHeight,
                       connector->count_modes);

                for (j = 0; j < connector->count_encoders; j++)
                        printf("%s%d", j > 0 ? ", " : "", 
connector->encoders[j]);
                printf("\n");

                if (!connector->count_modes)
                        continue;

                printf("  modes:\n");
                printf("  name refresh (Hz) hdisp hss hse htot vdisp "
                       "vss vse vtot)\n");
                for (j = 0; j < connector->count_modes; j++)
                        dump_mode(&connector->modes[j]);

                drmModeFreeConnector(connector);

                printf("  props:\n");
                dump_props(connector);
        }
        printf("\n");
}

void dump_crtcs(void)
{
        drmModeCrtc *crtc;
        int i;

        printf("CRTCs:\n");
        printf("id\tfb\tpos\tsize\n");
        for (i = 0; i < resources->count_crtcs; i++) {
                crtc = drmModeGetCrtc(fd, resources->crtcs[i]);

                if (!crtc) {
                        fprintf(stderr, "could not get crtc %i: %s\n",
                                resources->crtcs[i], strerror(errno));
                        continue;
                }
                printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
                       crtc->crtc_id,
                       crtc->buffer_id,
                       crtc->x, crtc->y,
                       crtc->width, crtc->height);
                dump_mode(&crtc->mode);

                drmModeFreeCrtc(crtc);
        }
        printf("\n");
}

void dump_framebuffers(void)
{
        drmModeFB *fb;
        int i;

        printf("Frame buffers:\n");
        printf("id\tsize\tpitch\n");
        for (i = 0; i < resources->count_fbs; i++) {
                fb = drmModeGetFB(fd, resources->fbs[i]);

                if (!fb) {
                        fprintf(stderr, "could not get fb %i: %s\n",
                                resources->fbs[i], strerror(errno));
                        continue;
                }
                printf("%d\t(%dx%d)\t%d\n",
                       fb->fb_id,
                       fb->width, fb->height);

                drmModeFreeFB(fb);
        }
        printf("\n");
}

/*
* Mode setting with the kernel interfaces is a bit of a chore.
* First you have to find the connector in question and make sure the
* requested mode is available.
* Then you need to find the encoder attached to that connector so you
* can bind it with a free crtc.
*/
struct connector {
        int id;
        char mode_str[64];
        drmModeModeInfo *mode;
        drmModeEncoder *encoder;
        int crtc;
        unsigned int fb_id[2], current_fb_id;
        struct timeval start;

        int swap_count;
};      

static void
connector_find_mode(struct connector *c)
{
        drmModeConnector *connector;
        int i, j, size, ret, width, height;

        /* First, find the connector & mode */
        c->mode = NULL;
        for (i = 0; i < resources->count_connectors; i++) {
                connector = drmModeGetConnector(fd, resources->connectors[i]);

                if (!connector) {
                        fprintf(stderr, "could not get connector %i: %s\n",
                                resources->connectors[i], strerror(errno));
                        drmModeFreeConnector(connector);
                        continue;
                }

                if (!connector->count_modes) {
                        drmModeFreeConnector(connector);
                        continue;
                }

                if (connector->connector_id != c->id) {
                        drmModeFreeConnector(connector);
                        continue;
                }

                for (j = 0; j < connector->count_modes; j++) {
                        c->mode = &connector->modes[j];
                        if (!strcmp(c->mode->name, c->mode_str))
                                break;
                }

                /* Found it, break out */
                if (c->mode)
                        break;

                drmModeFreeConnector(connector);
        }

        if (!c->mode) {
                fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
                return;
        }

        /* Now get the encoder */
        for (i = 0; i < resources->count_encoders; i++) {
                c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);

                if (!c->encoder) {
                        fprintf(stderr, "could not get encoder %i: %s\n",
                                resources->encoders[i], strerror(errno));
                        drmModeFreeEncoder(c->encoder);
                        continue;
                }

                if (c->encoder->encoder_id  == connector->encoder_id)
                        break;

                drmModeFreeEncoder(c->encoder);
        }

        if (c->crtc == -1)
                c->crtc = c->encoder->crtc_id;
}

static int
create_test_buffer(struct kms_driver *driver,
                   int width, int height, int *stride_out, struct kms_bo 
**bo_out)
{
        struct kms_bo *bo;
        uint32_t *fb_ptr;
        int size, ret, i, stride;
        div_t d;
        void *ptr;

        /* Mode size at 32 bpp */
        stride = width * 4;
        size = stride * height;

        unsigned attrs[7] = {
               KMS_WIDTH, width,
               KMS_HEIGHT, height,
               KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
               KMS_TERMINATE_PROP_LIST,
       };


        if (kms_bo_create(driver, attrs, &bo)<0) {
                fprintf(stderr, "failed to alloc buffer: %s\n",
                        strerror(errno));
                return -1;
        }

        if (kms_bo_map(bo, &ptr)<0) {
                fprintf(stderr, "failed to GTT map buffer: %s\n",
                        strerror(errno));
                return -1;
        }
        fb_ptr = ptr;
        fprintf(stderr, "fb_ptr is %p\n", fb_ptr);

        /* paint the buffer with colored tiles */
        for (i = 0; i < width * height; i++) {
                d = div(i, width);
                //fb_ptr[i] = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem 
>> 6);
                fb_ptr[i] = 0xffffffff;
        }

        kms_bo_unmap(bo);

        *bo_out = bo;
        *stride_out = stride;

        return 0;
}

static void
set_mode(struct connector *c, int count, int page_flip)
{
        drmModeConnector *connector;
        drmModeEncoder *encoder = NULL;
        struct drm_mode_modeinfo *mode = NULL;
        struct kms_driver *driver;
        struct kms_bo *bo, *other_bo;
        unsigned int fb_id, other_fb_id;
        int i, j, ret, width, height, x, stride;
        drmEventContext evctx;

        width = 0;
        height = 0;
        for (i = 0; i < count; i++) {
                connector_find_mode(&c[i]);
                if (c[i].mode == NULL)
                        continue;
                width += c[i].mode->hdisplay;
                if (height < c[i].mode->vdisplay)
                        height = c[i].mode->vdisplay;
        }

        if (kms_create(fd, &driver)<0) {
                fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno));
                return;
        }

        if (create_test_buffer(driver, width, height, &stride, &bo))
                return;

        fprintf(stderr, "pitch is: %d\n", bo->pitch);
        ret = drmModeAddFB(fd, width, height, 32, 32, bo->pitch, bo->handle,
                           &fb_id);
        if (ret) {
                fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
                return;
        }

        fprintf(stderr, "fb_id is :%08X\n", fb_id);

        x = 0;
        for (i = 0; i < count; i++) {
                if (c[i].mode == NULL)
                        continue;

                printf("setting mode %s on connector %d, crtc %d\n",
                       c[i].mode_str, c[i].id, c[i].crtc);

                ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
                                     &c[i].id, 1, c[i].mode);

                drmModeDirtyFB(fd, fb_id, NULL, 0);

                x += c[i].mode->hdisplay;

                if (ret) {
                        fprintf(stderr, "failed to set mode: %s\n", 
strerror(errno));
                        return;
                }
        }

        return;
}

extern char *optarg;
extern int optind, opterr, optopt;
static char optstr[] = "ecpmfs:v";

void usage(char *name)
{
        fprintf(stderr, "usage: %s [-ecpmf]\n", name);
        fprintf(stderr, "\t-e\tlist encoders\n");
        fprintf(stderr, "\t-c\tlist connectors\n");
        fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
        fprintf(stderr, "\t-m\tlist modes\n");
        fprintf(stderr, "\t-f\tlist framebuffers\n");
        fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
        fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
        fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
        fprintf(stderr, "\n\tDefault is to dump all info.\n");
        exit(0);
}

#define dump_resource(res) if (res) dump_##res()


int main(int argc, char **argv)
{
        int c;
        int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
        int test_vsync = 0;
        char *modules[] = { "vmwgfx", "i915", "radeon" };
        char *modeset = NULL, *mode, *connector;
        int i, connector_id, count = 0;
        struct connector con_args[2];
        
        opterr = 0;
        while ((c = getopt(argc, argv, optstr)) != -1) {
                switch (c) {
                case 'e':
                        encoders = 1;
                        break;
                case 'c':
                        connectors = 1;
                        break;
                case 'p':
                        crtcs = 1;
                        break;
                case 'm':
                        modes = 1;
                        break;
                case 'f':
                        framebuffers = 1;
                        break;
                case 'v':
                        test_vsync = 1;
                        break;
                case 's':
                        modeset = strdup(optarg);
                        con_args[count].crtc = -1;
                        if (sscanf(optarg, "%d:%64s",
                                   &con_args[count].id,
                                   &con_args[count].mode_str) != 2 &&
                            sscanf(optarg, "%...@%d:%64s",
                                   &con_args[count].id,
                                   &con_args[count].crtc,
                                   &con_args[count].mode_str) != 3)
                                usage(argv[0]);
count++; break;
                default:
                        usage(argv[0]);
                        break;
                }
        }

        if (argc == 1)
                encoders = connectors = crtcs = modes = framebuffers = 1;

        for (i = 0; i < ARRAY_SIZE(modules); i++) {
                printf("trying to load module %s...", modules[i]);
                fd = drmOpen(modules[i], NULL);
                if (fd < 0) {
                        printf("failed.\n");
                } else {
                        printf("success.\n");
                        break;
                }
        }

        if (test_vsync && 1) {
                fprintf(stderr, "page flipping not supported by drm.\n");
                return -1;
        }

        if (i == ARRAY_SIZE(modules)) {
                fprintf(stderr, "failed to load any modules, aborting.\n");
                return -1;
        }

        resources = drmModeGetResources(fd);
        if (!resources) {
                fprintf(stderr, "drmModeGetResources failed: %s\n",
                        strerror(errno));
                drmClose(fd);
                return 1;
        }

        dump_resource(encoders);
        dump_resource(connectors);
        dump_resource(crtcs);
        dump_resource(framebuffers);

        if (count > 0) {
                set_mode(con_args, count, test_vsync);
                getchar();
        }

        drmModeFreeResources(resources);

        return 0;
}
------------------------------------------------------------------------------
SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
http://p.sf.net/sfu/solaris-dev2dev
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to