1 #include "main/glheader.h"
2 #include "glapi/glthread.h"
3 #include <GL/internal/glcore.h>
6 #include "state_tracker/st_public.h"
7 #include "pipe/p_defines.h"
8 #include "pipe/p_context.h"
10 #include "nouveau_context.h"
11 #include "nouveau_dri.h"
12 #include "nouveau_local.h"
13 #include "nouveau_screen.h"
14 #include "nouveau_winsys_pipe.h"
17 static const struct dri_debug_control debug_control
[] = {
21 int __nouveau_debug
= 0;
25 nouveau_context_create(const __GLcontextModes
*glVis
,
26 __DRIcontextPrivate
*driContextPriv
,
27 void *sharedContextPrivate
)
29 __DRIscreenPrivate
*driScrnPriv
= driContextPriv
->driScreenPriv
;
30 struct nouveau_screen
*nv_screen
= driScrnPriv
->private;
31 struct nouveau_context
*nv
= CALLOC_STRUCT(nouveau_context
);
32 struct nouveau_device_priv
*nvdev
;
33 struct pipe_context
*pipe
= NULL
;
34 struct st_context
*st_share
= NULL
;
37 if (sharedContextPrivate
) {
38 st_share
= ((struct nouveau_context
*)sharedContextPrivate
)->st
;
41 if ((ret
= nouveau_device_get_param(nv_screen
->device
,
42 NOUVEAU_GETPARAM_CHIPSET_ID
,
44 NOUVEAU_ERR("Error determining chipset id: %d\n", ret
);
48 if ((ret
= nouveau_channel_alloc(nv_screen
->device
,
49 0x8003d001, 0x8003d002,
51 NOUVEAU_ERR("Error creating GPU channel: %d\n", ret
);
55 driContextPriv
->driverPrivate
= (void *)nv
;
56 nv
->nv_screen
= nv_screen
;
57 nv
->dri_screen
= driScrnPriv
;
59 nvdev
= nouveau_device(nv_screen
->device
);
60 nvdev
->ctx
= driContextPriv
->hHWContext
;
61 nvdev
->lock
= (drmLock
*)&driScrnPriv
->pSAREA
->lock
;
63 driParseConfigFiles(&nv
->dri_option_cache
, &nv_screen
->option_cache
,
64 nv
->dri_screen
->myNum
, "nouveau");
66 __nouveau_debug
= driParseDebugString(getenv("NOUVEAU_DEBUG"),
70 /*XXX: Hack up a fake region and buffer object for front buffer.
71 * This will go away with TTM, replaced with a simple reference
72 * of the front buffer handle passed to us by the DDX.
75 struct pipe_surface
*fb_surf
;
76 struct nouveau_bo_priv
*fb_bo
;
78 fb_bo
= calloc(1, sizeof(struct nouveau_bo_priv
));
79 fb_bo
->drm
.offset
= nv_screen
->front_offset
;
80 fb_bo
->drm
.flags
= NOUVEAU_MEM_FB
;
81 fb_bo
->drm
.size
= nv_screen
->front_pitch
*
82 nv_screen
->front_height
;
84 fb_bo
->base
.flags
= NOUVEAU_BO_PIN
| NOUVEAU_BO_VRAM
;
85 fb_bo
->base
.offset
= fb_bo
->drm
.offset
;
86 fb_bo
->base
.handle
= (unsigned long)fb_bo
;
87 fb_bo
->base
.size
= fb_bo
->drm
.size
;
88 fb_bo
->base
.device
= nv_screen
->device
;
90 fb_surf
= calloc(1, sizeof(struct pipe_surface
));
91 fb_surf
->cpp
= nv_screen
->front_cpp
;
92 fb_surf
->pitch
= nv_screen
->front_pitch
/ fb_surf
->cpp
;
93 fb_surf
->height
= nv_screen
->front_height
;
94 fb_surf
->refcount
= 1;
95 fb_surf
->buffer
= (void *)fb_bo
;
97 nv
->frontbuffer
= fb_surf
;
100 if ((ret
= nouveau_grobj_alloc(nv
->channel
, 0x00000000, 0x30,
102 NOUVEAU_ERR("Error creating NULL object: %d\n", ret
);
105 nv
->next_handle
= 0x80000000;
107 if ((ret
= nouveau_notifier_alloc(nv
->channel
, nv
->next_handle
++, 1,
108 &nv
->sync_notifier
))) {
109 NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret
);
113 if (nv
->chipset
< 0x50)
114 ret
= nouveau_surface_init_nv04(nv
);
116 ret
= nouveau_surface_init_nv50(nv
);
121 if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
122 pipe
= nouveau_pipe_create(nv
);
124 NOUVEAU_ERR("Couldn't create hw pipe\n");
128 NOUVEAU_MSG("Using softpipe\n");
129 pipe
= nouveau_create_softpipe(nv
);
131 NOUVEAU_ERR("Error creating pipe, bailing\n");
137 nv
->st
= st_create_context(pipe
, glVis
, st_share
);
142 nouveau_context_destroy(__DRIcontextPrivate
*driContextPriv
)
144 struct nouveau_context
*nv
= driContextPriv
->driverPrivate
;
148 st_flush(nv
->st
, PIPE_FLUSH_WAIT
);
149 st_destroy_context(nv
->st
);
151 nouveau_grobj_free(&nv
->NvCtxSurf2D
);
152 nouveau_grobj_free(&nv
->NvImageBlit
);
153 nouveau_channel_free(&nv
->channel
);
159 nouveau_context_bind(__DRIcontextPrivate
*driContextPriv
,
160 __DRIdrawablePrivate
*driDrawPriv
,
161 __DRIdrawablePrivate
*driReadPriv
)
163 struct nouveau_context
*nv
;
164 struct nouveau_framebuffer
*draw
, *read
;
166 if (!driContextPriv
) {
167 st_make_current(NULL
, NULL
, NULL
);
171 nv
= driContextPriv
->driverPrivate
;
172 draw
= driDrawPriv
->driverPrivate
;
173 read
= driReadPriv
->driverPrivate
;
175 st_make_current(nv
->st
, draw
->stfb
, read
->stfb
);
177 if ((nv
->dri_drawable
!= driDrawPriv
) ||
178 (nv
->last_stamp
!= driDrawPriv
->lastStamp
)) {
179 nv
->dri_drawable
= driDrawPriv
;
180 st_resize_framebuffer(draw
->stfb
, driDrawPriv
->w
,
182 nv
->last_stamp
= driDrawPriv
->lastStamp
;
185 if (driDrawPriv
!= driReadPriv
) {
186 st_resize_framebuffer(read
->stfb
, driReadPriv
->w
,
194 nouveau_context_unbind(__DRIcontextPrivate
*driContextPriv
)
196 struct nouveau_context
*nv
= driContextPriv
->driverPrivate
;