summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
blob: ce1546a034475791c1c5e0df1457c8ade9ba26b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
    /* Copyright (c) 2001, Stanford University
 * All rights reserved
 *
 * See the file LICENSE.txt for information on redistributing this software.
 */

#include <string.h>
#include "cr_mem.h"
#include "cr_environment.h"
#include "cr_string.h"
#include "cr_error.h"
#include "cr_glstate.h"
#include "server.h"

#ifdef WINDOWS
#pragma warning( disable: 4706 )
#endif

static void
setDefaults(void)
{
    if (!cr_server.tcpip_port)
        cr_server.tcpip_port = DEFAULT_SERVER_PORT;
    cr_server.run_queue = NULL;
    cr_server.optimizeBucket = 1;
    cr_server.useL2 = 0;
    cr_server.maxBarrierCount = 0;
    cr_server.ignore_papi = 0;
    cr_server.only_swap_once = 0;
    cr_server.overlapBlending = 0;
    cr_server.debug_barriers = 0;
    cr_server.sharedDisplayLists = 0;
    cr_server.sharedTextureObjects = 0;
    cr_server.sharedPrograms = 0;
    cr_server.sharedWindows = 0;
    cr_server.useDMX = 0;
    cr_server.vpProjectionMatrixParameter = -1;
    cr_server.vpProjectionMatrixVariable = NULL;
    cr_server.currentProgram = 0;

    cr_server.num_overlap_intens = 0;
    cr_server.overlap_intens = 0;
    crMemset(&cr_server.MainContextInfo, 0, sizeof (cr_server.MainContextInfo));

    crMatrixInit(&cr_server.viewMatrix[0]);
    crMatrixInit(&cr_server.viewMatrix[1]);
    crMatrixInit(&cr_server.projectionMatrix[0]);
    crMatrixInit(&cr_server.projectionMatrix[1]);
    cr_server.currentEye = -1;

    cr_server.uniqueWindows = 0;

    cr_server.screenCount = 0;
    cr_server.bUsePBOForReadback = GL_FALSE;
    cr_server.bWindowsInitiallyHidden = GL_FALSE;

    cr_server.pfnNotifyEventCB = NULL;
}

/* Check if host reports minimal OpenGL capabilities.
 *
 * Require OpenGL 2.1 or later.
 *
 * For example, on Windows host this may happen if host has no graphics
 * card drivers installed or drivers were not properly signed or VBox
 * is running via remote desktop session etc. Currently, we take care
 * about Windows host only when specific RENDERER and VERSION strings
 * returned in this case. Later this check should be expanded to the
 * rest of hosts. */
static bool crServerHasInsufficientCaps()
{
    const char *pszRealVersion;
    int rc;
    uint32_t u32VerMajor = 0;
    uint32_t u32VerMinor = 0;
    char *pszNext = NULL;

    if (!cr_server.head_spu)
        return true;

    pszRealVersion = (const char *)cr_server.head_spu->dispatch_table.GetString(GL_REAL_VERSION);
    if (!pszRealVersion)
        return true; /* No version == insufficient. */

    rc = RTStrToUInt32Ex(pszRealVersion, &pszNext, 10, &u32VerMajor);
    if (   RT_SUCCESS(rc)
        && *pszNext == '.')
            RTStrToUInt32Ex(pszNext + 1, NULL, 10, &u32VerMinor);

    crInfo("Host supports version %d.%d [%s]", u32VerMajor, u32VerMinor, pszRealVersion);

    if (   u32VerMajor > 2
        || (u32VerMajor == 2 && u32VerMinor >= 1))
        return false; /* >= 2.1, i.e. good enough. */

    return true; /* Insufficient. */
}

void crServerSetVBoxConfiguration()
{
    CRMuralInfo *defaultMural;
    char response[8096];

    char **spuchain;
    int num_spus;
    int *spu_ids;
    char **spu_names;
    char *spu_dir = NULL;
    int i;
    /* Quadrics defaults */
    int my_rank = 0;
    int low_context = CR_QUADRICS_DEFAULT_LOW_CONTEXT;
    int high_context = CR_QUADRICS_DEFAULT_HIGH_CONTEXT;
    unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    char hostname[1024];
    char **clientchain, **clientlist;
    GLint dims[4];
    const char * env;

    defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
    CRASSERT(defaultMural);

    setDefaults();

    /*
     * Get my hostname
     */
    if (crGetHostname(hostname, sizeof(hostname)))
    {
        crError("CRServer: Couldn't get my own hostname?");
    }

#ifdef VBOX_WITH_CR_DISPLAY_LISTS
    strcpy(response, "1 0 expando");
#else
    strcpy(response, "1 0 render");
#endif
    crDebug("CRServer: my SPU chain: %s", response);

    /* response will describe the SPU chain.
     * Example "2 5 wet 6 render"
     */
    spuchain = crStrSplit(response, " ");
    num_spus = crStrToInt(spuchain[0]);
    spu_ids = (int *) crAlloc(num_spus * sizeof(*spu_ids));
    spu_names = (char **) crAlloc((num_spus + 1) * sizeof(*spu_names));
    for (i = 0; i < num_spus; i++)
    {
        spu_ids[i] = crStrToInt(spuchain[2 * i + 1]);
        spu_names[i] = crStrdup(spuchain[2 * i + 2]);
        crDebug("SPU %d/%d: (%d) \"%s\"", i + 1, num_spus, spu_ids[i],
                        spu_names[i]);
    }
    spu_names[i] = NULL;

    crNetSetRank(0);
    crNetSetContextRange(32, 35);
    crNetSetNodeRange("iam0", "iamvis20");
    crNetSetKey(key,sizeof(key));
    crNetSetKey(key,sizeof(key));
    cr_server.tcpip_port = 7000;

    crDebug("CRServer: my port number is %d", cr_server.tcpip_port);

    /*
     * Load the SPUs
     */
    cr_server.head_spu =
        crSPULoadChain(num_spus, spu_ids, spu_names, spu_dir, &cr_server);

    env = crGetenv( "CR_SERVER_DEFAULT_VISUAL_BITS" );
    if (env != NULL && env[0] != '\0')
    {
        unsigned int bits = (unsigned int)crStrParseI32(env, 0);
        if (bits <= CR_ALL_BITS)
            cr_server.fVisualBitsDefault = bits;
        else
            crWarning("invalid bits option %c", bits);
    }
    else
        cr_server.fVisualBitsDefault = CR_RGB_BIT | CR_ALPHA_BIT | CR_DOUBLE_BIT;

    env = crGetenv("CR_SERVER_CAPS");
    if (env && env[0] != '\0')
    {
        cr_server.u32Caps = crStrParseI32(env, 0);
        cr_server.u32Caps &= CR_VBOX_CAPS_ALL;
    }
    else
    {
        cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT
                | CR_VBOX_CAP_CMDVBVA
                | CR_VBOX_CAP_CMDBLOCKS
                | CR_VBOX_CAP_GETATTRIBSLOCATIONS
                | CR_VBOX_CAP_CMDBLOCKS_FLUSH
                ;
    }

    if (crServerHasInsufficientCaps())
    {
        crDebug("Cfg: report minimal OpenGL capabilities");
        cr_server.u32Caps |= CR_VBOX_CAP_HOST_CAPS_NOT_SUFFICIENT;
    }

    crInfo("Cfg: u32Caps(%#x), fVisualBitsDefault(%#x)",
            cr_server.u32Caps,
            cr_server.fVisualBitsDefault);

    /* Need to do this as early as possible */

    cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]);
    cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]);
    
    defaultMural->gX = dims[0];
    defaultMural->gY = dims[1];
    defaultMural->width = dims[2];
    defaultMural->height = dims[3];

    crFree(spu_ids);
    crFreeStrings(spu_names);
    crFreeStrings(spuchain);
    if (spu_dir)
        crFree(spu_dir);

    cr_server.mtu = 1024 * 30;

    /*
     * Get a list of all the clients talking to me.
     */
    if (cr_server.vncMode) {
        /* we're inside a vnc viewer */
        /*if (!crMothershipSendString( conn, response, "getvncclient %s", hostname ))
            crError( "Bad Mothership response: %s", response );*/
    }
    else {
        //crMothershipGetClients(conn, response);
        strcpy(response, "1 tcpip 1");
    }

    crDebug("CRServer: my clients: %s", response);

    /*
     * 'response' will now contain a number indicating the number of clients
     * of this server, followed by a comma-separated list of protocol/SPU ID
     * pairs.
     * Example: "3 tcpip 1,gm 2,via 10"
     */
    clientchain = crStrSplitn(response, " ", 1);
    cr_server.numClients = crStrToInt(clientchain[0]);
    if (cr_server.numClients == 0)
    {
        crError("I have no clients!  What's a poor server to do?");
    }
    clientlist = crStrSplit(clientchain[1], ",");

    /*
     * Connect to initial set of clients.
     * Call crNetAcceptClient() for each client.
     * Also, look for a client that's _not_ using the file: protocol.
     */
    for (i = 0; i < cr_server.numClients; i++)
    {
        CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient));
#ifdef VBOX
        sscanf(clientlist[i], "%1023s %d", cr_server.protocol, &(newClient->spu_id));
#else
        sscanf(clientlist[i], "%s %d", cr_server.protocol, &(newClient->spu_id));
#endif
        newClient->conn = crNetAcceptClient(cr_server.protocol, NULL,
                                            cr_server.tcpip_port,
                                            cr_server.mtu, 0);
        newClient->currentCtxInfo = &cr_server.MainContextInfo;
        crServerAddToRunQueue(newClient);

        cr_server.clients[i] = newClient;
    }

    /* set default client and mural */
    if (cr_server.numClients > 0) {
         cr_server.curClient = cr_server.clients[0];
         cr_server.curClient->currentMural = defaultMural;
         cr_server.client_spu_id =cr_server.clients[0]->spu_id;
    }

    crFreeStrings(clientchain);
    crFreeStrings(clientlist);

    /* Ask the mothership for the tile info */
    //crServerGetTileInfoFromMothership(conn, defaultMural);

    if (cr_server.vncMode) {
        /* In vnc mode, we reset the mothership configuration so that it can be
         * used by subsequent OpenGL apps without having to spawn a new mothership
         * on a new port.
         */
        crDebug("CRServer: Resetting mothership to initial state");
        //crMothershipReset(conn);
    }

    //crMothershipDisconnect(conn);
}

void crServerSetVBoxConfigurationHGCM()
{
    CRMuralInfo *defaultMural;

#ifdef VBOX_WITH_CR_DISPLAY_LISTS
    int spu_ids[1]     = {0};
    char *spu_names[1] = {"expando"};
#else
    int spu_ids[1]     = {0};
    char *spu_names[1] = {"render"};
#endif
    char *spu_dir = NULL;
    int i;
    GLint dims[4];
    const char * env;

    defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
    CRASSERT(defaultMural);

    /// @todo should be moved to addclient so we have a chain for each client

    setDefaults();
    
    /* Load the SPUs */    
    cr_server.head_spu = crSPULoadChain(1, spu_ids, spu_names, spu_dir, &cr_server);

    if (!cr_server.head_spu)
        return;


    env = crGetenv( "CR_SERVER_DEFAULT_VISUAL_BITS" );
    if (env != NULL && env[0] != '\0')
    {
        unsigned int bits = (unsigned int)crStrParseI32(env, 0);
        if (bits <= CR_ALL_BITS)
            cr_server.fVisualBitsDefault = bits;
        else
            crWarning("invalid bits option %c", bits);
    }
    else
        cr_server.fVisualBitsDefault = CR_RGB_BIT | CR_ALPHA_BIT | CR_DOUBLE_BIT;


    env = crGetenv("CR_SERVER_CAPS");
    if (env && env[0] != '\0')
    {
        cr_server.u32Caps = crStrParseI32(env, 0);
        cr_server.u32Caps &= CR_VBOX_CAPS_ALL;
    }
    else
    {
        cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT
                | CR_VBOX_CAP_CMDVBVA
                | CR_VBOX_CAP_CMDBLOCKS
                | CR_VBOX_CAP_GETATTRIBSLOCATIONS
                | CR_VBOX_CAP_CMDBLOCKS_FLUSH
                ;
    }

    if (crServerHasInsufficientCaps())
    {
        crDebug("Cfg: report minimal OpenGL capabilities");
        cr_server.u32Caps |= CR_VBOX_CAP_HOST_CAPS_NOT_SUFFICIENT;
    }

    crInfo("Cfg: u32Caps(%#x), fVisualBitsDefault(%#x)",
            cr_server.u32Caps,
            cr_server.fVisualBitsDefault);

    cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]);
    cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]);
    
    defaultMural->gX = dims[0];
    defaultMural->gY = dims[1];
    defaultMural->width = dims[2];
    defaultMural->height = dims[3];

    cr_server.mtu = 1024 * 250;

    cr_server.numClients = 0;
    strcpy(cr_server.protocol, "vboxhgcm");

    for (i = 0; i < cr_server.numClients; i++)
    {
        CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient));
        newClient->spu_id = 0;
        newClient->conn = crNetAcceptClient(cr_server.protocol, NULL,
                                            cr_server.tcpip_port,
                                            cr_server.mtu, 0);
        newClient->currentCtxInfo = &cr_server.MainContextInfo;
        crServerAddToRunQueue(newClient);

        cr_server.clients[i] = newClient;
    }

    /* set default client and mural */
    if (cr_server.numClients > 0) {
         cr_server.curClient = cr_server.clients[0];
         cr_server.curClient->currentMural = defaultMural;
         cr_server.client_spu_id =cr_server.clients[0]->spu_id;
    }
}