PS2GL
OpenGL*-like API for the PS2
Loading...
Searching...
No Matches
immgmanager.cpp
1/* Copyright (C) 2000,2001,2002 Sony Computer Entertainment America
2
3 This file is subject to the terms and conditions of the GNU Lesser
4 General Public License Version 2.1. See the file "COPYING" in the
5 main directory of this archive for more details. */
6
7#include <stdio.h>
8
9#include "ps2s/cpu_matrix.h"
10#include "ps2s/displayenv.h"
11#include "ps2s/math.h"
12#include "ps2s/packet.h"
13
14#include "GL/ps2gl.h"
15#include "ps2gl/clear.h"
16#include "ps2gl/dlist.h"
17#include "ps2gl/drawcontext.h"
18#include "ps2gl/glcontext.h"
19#include "ps2gl/gmanager.h"
20#include "ps2gl/material.h"
21#include "ps2gl/matrix.h"
22#include "ps2gl/renderer.h"
23#include "ps2gl/texture.h"
24
25using namespace ArrayType;
26
27/********************************************
28 * CImmGeomManager
29 */
30
31CImmGeomManager::CImmGeomManager(CGLContext& context, int immBufferQwordSize)
32 : CGeomManager(context)
33 , RendererManager(context)
34 , VertexBuf0(immBufferQwordSize + immBufferQwordSize % 4,
35 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
36 , NormalBuf0(immBufferQwordSize * 4 / 3 + 1 + (immBufferQwordSize * 4 / 3 + 1) % 4,
37 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
38 , TexCoordBuf0(immBufferQwordSize / 2 + (immBufferQwordSize / 2) % 4,
39 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
40 , ColorBuf0(immBufferQwordSize + immBufferQwordSize % 4,
41 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
42 , VertexBuf1(immBufferQwordSize + immBufferQwordSize % 4,
43 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
44 , NormalBuf1(immBufferQwordSize * 4 / 3 + 1 + (immBufferQwordSize * 4 / 3 + 1) % 4,
45 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
46 , TexCoordBuf1(immBufferQwordSize / 2 + (immBufferQwordSize / 2) % 4,
47 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
48 , ColorBuf1(immBufferQwordSize + immBufferQwordSize % 4,
49 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl)
50{
51 CurVertexBuf = &VertexBuf0;
52 CurNormalBuf = &NormalBuf0;
53 CurTexCoordBuf = &TexCoordBuf0;
54 CurColorBuf = &ColorBuf0;
55
56 VertArray = new CVertArray;
57
58 RendererManager.ArrayAccessChanged(RendererProps::kLinear);
59}
60
61CImmGeomManager::~CImmGeomManager()
62{
63 delete VertArray;
64}
65
66void CImmGeomManager::SwapBuffers()
67{
68 // flip the geometry buffers
69 if (CurVertexBuf == &VertexBuf0)
70 CurVertexBuf = &VertexBuf1;
71 else
72 CurVertexBuf = &VertexBuf0;
73 CurVertexBuf->Reset();
74 if (CurNormalBuf == &NormalBuf0)
75 CurNormalBuf = &NormalBuf1;
76 else
77 CurNormalBuf = &NormalBuf0;
78 CurNormalBuf->Reset();
79 if (CurTexCoordBuf == &TexCoordBuf0)
80 CurTexCoordBuf = &TexCoordBuf1;
81 else
82 CurTexCoordBuf = &TexCoordBuf0;
83 CurTexCoordBuf->Reset();
84 if (CurColorBuf == &ColorBuf0)
85 CurColorBuf = &ColorBuf1;
86 else
87 CurColorBuf = &ColorBuf0;
88 CurColorBuf->Reset();
89}
90
91/********************************************
92 * glBegin/glEnd and related
93 */
94
95void CImmGeomManager::BeginGeom(GLenum mode)
96{
97 if (Prim != mode)
98 PrimChanged(mode);
99
100 Geometry.SetPrimType(mode);
101 Geometry.SetArrayType(kLinear);
102
103 Geometry.SetNormals(CurNormalBuf->GetNextPtr());
104 Geometry.SetVertices(CurVertexBuf->GetNextPtr());
105 Geometry.SetTexCoords(CurTexCoordBuf->GetNextPtr());
106 Geometry.SetColors(CurColorBuf->GetNextPtr());
107
108 InsideBeginEnd = true;
109}
110
111void CImmGeomManager::Vertex(cpu_vec_xyzw newVert)
112{
113 cpu_vec_xyz normal = GetCurNormal();
114 *CurNormalBuf += normal;
115
116 const float* texCoord = GetCurTexCoord();
117 *CurTexCoordBuf += texCoord[0];
118 *CurTexCoordBuf += texCoord[1];
119
120 *CurVertexBuf += newVert;
121
122 Geometry.AddVertices();
123 Geometry.AddNormals();
124 Geometry.AddTexCoords();
125}
126
127void CImmGeomManager::Normal(cpu_vec_xyz normal)
128{
129 if (DoNormalize)
130 normal.normalize();
131 CurNormal = normal;
132}
133
134void CImmGeomManager::Color(cpu_vec_xyzw color)
135{
136 if (InsideBeginEnd) {
137 *CurColorBuf += color;
138 Geometry.AddColors();
139 } else {
140 GLContext.GetMaterialManager().Color(color);
141 }
142}
143
144void CImmGeomManager::TexCoord(float u, float v)
145{
146 CurTexCoord[0] = u;
147 CurTexCoord[1] = v;
148}
149
150void CImmGeomManager::EndGeom()
151{
152 InsideBeginEnd = false;
153
154 Geometry.SetVerticesAreValid(true);
155 Geometry.SetNormalsAreValid(true);
156 Geometry.SetTexCoordsAreValid(true);
157
158 // check colors
159 Geometry.SetColorsAreValid(false);
160 if (Geometry.GetNumNewColors() > 0) {
161 mErrorIf(Geometry.GetNumNewVertices() != Geometry.GetNumNewColors(),
162 "Sorry, but inside glBegin/glEnd you need "
163 "to specify either one color for each vertex given, or none.");
164 Geometry.SetColorsAreValid(true);
165
166 SyncColorMaterial(true);
167 } else {
168 SyncColorMaterial(false);
169 }
170
171 Geometry.SetWordsPerVertex(4);
172 Geometry.SetWordsPerNormal(3);
173 Geometry.SetWordsPerTexCoord(2);
174 Geometry.SetWordsPerColor(4);
175
176 CommitNewGeom();
177}
178
179/********************************************
180 * DrawArrays
181 */
182
183void CImmGeomManager::DrawArrays(GLenum mode, int first, int count)
184{
185 if (Prim != mode)
186 PrimChanged(mode);
187
188 Geometry.SetPrimType(mode);
189 Geometry.SetArrayType(kLinear);
190
191 Geometry.SetVertices(VertArray->GetVertices());
192 Geometry.SetNormals(VertArray->GetNormals());
193 Geometry.SetTexCoords(VertArray->GetTexCoords());
194 Geometry.SetColors(VertArray->GetColors());
195
196 Geometry.SetVerticesAreValid(VertArray->GetVerticesAreValid());
197 Geometry.SetNormalsAreValid(VertArray->GetNormalsAreValid());
198 Geometry.SetTexCoordsAreValid(VertArray->GetTexCoordsAreValid());
199 Geometry.SetColorsAreValid(VertArray->GetColorsAreValid());
200
201 Geometry.SetWordsPerVertex(VertArray->GetWordsPerVertex());
202 Geometry.SetWordsPerNormal(VertArray->GetWordsPerNormal());
203 Geometry.SetWordsPerTexCoord(VertArray->GetWordsPerTexCoord());
204 Geometry.SetWordsPerColor(VertArray->GetWordsPerColor());
205
206 Geometry.AddVertices(count);
207 Geometry.AddNormals(count);
208 Geometry.AddTexCoords(count);
209 Geometry.AddColors(count);
210
211 Geometry.AdjustNewGeomPtrs(first);
212
213 // do this before sync'ing the vu1 renderer in CommitNewGeom
214 SyncColorMaterial(VertArray->GetColors() != NULL);
215
216 CommitNewGeom();
217}
218
219void CImmGeomManager::DrawingIndexedArray()
220{
221 if (!LastArrayAccessIsValid || !LastArrayAccessWasIndexed) {
222 GLContext.ArrayAccessChanged();
223 RendererManager.ArrayAccessChanged(RendererProps::kIndexed);
224 LastArrayAccessIsValid = true;
225 }
226 LastArrayAccessWasIndexed = true;
227}
228
229void CImmGeomManager::DrawIndexedArrays(GLenum primType,
230 int numIndices, const unsigned char* indices,
231 int numVertices)
232{
233 /*
234 // make sure there's no pending geometry
235 Flush();
236
237 // do these before sync'ing the vu1 renderer
238 SyncColorMaterial(VertArray->GetColors() != NULL);
239 DrawingIndexedArray();
240
241 // now update the renderer and render
242
243 bool rendererChanged = RendererManager.UpdateRenderer();
244
245 if ( rendererChanged ) {
246 RendererManager.LoadRenderer(GLContext.GetVif1Packet());
247 }
248 SyncRendererContext(primType);
249 SyncGsContext();
250
251 RendererManager.GetCurRenderer().DrawIndexedArrays( primType, numIndices, indices,
252 numVertices, *VertArray );
253 */
254 if (Prim != primType)
255 PrimChanged(primType);
256
257 Geometry.SetPrimType(primType);
258 Geometry.SetArrayType(kIndexed);
259
260 Geometry.SetVertices(VertArray->GetVertices());
261 Geometry.SetNormals(VertArray->GetNormals());
262 Geometry.SetTexCoords(VertArray->GetTexCoords());
263 Geometry.SetColors(VertArray->GetColors());
264
265 Geometry.SetVerticesAreValid(VertArray->GetVerticesAreValid());
266 Geometry.SetNormalsAreValid(VertArray->GetNormalsAreValid());
267 Geometry.SetTexCoordsAreValid(VertArray->GetTexCoordsAreValid());
268 Geometry.SetColorsAreValid(VertArray->GetColorsAreValid());
269
270 Geometry.SetWordsPerVertex(VertArray->GetWordsPerVertex());
271 Geometry.SetWordsPerNormal(VertArray->GetWordsPerNormal());
272 Geometry.SetWordsPerTexCoord(VertArray->GetWordsPerTexCoord());
273 Geometry.SetWordsPerColor(VertArray->GetWordsPerColor());
274
275 Geometry.AddVertices(numVertices);
276 Geometry.AddNormals(numVertices);
277 Geometry.AddTexCoords(numVertices);
278 Geometry.AddColors(numVertices);
279
280 Geometry.SetNumIndices(numIndices);
281 Geometry.SetIndices(indices);
282 Geometry.SetIStripLengths(NULL);
283
284 // do this before sync'ing the vu1 renderer in CommitNewGeom
285 SyncColorMaterial(VertArray->GetColors() != NULL);
286
287 CommitNewGeom();
288}
289
290/********************************************
291 * common and synchronization code
292 */
293
294void CImmGeomManager::DrawingLinearArray()
295{
296 if (!LastArrayAccessIsValid || LastArrayAccessWasIndexed) {
297 GLContext.ArrayAccessChanged();
298 RendererManager.ArrayAccessChanged(RendererProps::kLinear);
299 LastArrayAccessIsValid = true;
300 }
301 LastArrayAccessWasIndexed = false;
302}
303
304void CImmGeomManager::CommitNewGeom()
305{
306 // do this before updating the renderer
307 if (Geometry.GetNewArrayType() == kLinear)
308 DrawingLinearArray();
309 else
310 DrawingIndexedArray();
311
312 bool doReset = true;
313 bool rendererChanged = RendererManager.UpdateNewRenderer();
314
315 if (Geometry.IsPending()) {
316
317 // FIXME: need to ask the renderer what context changes it cares about/updates
318
319 // if the context hasn't changed, try to merge the new geometry
320 // into the current block
321 if (GLContext.GetRendererContextChanged() == 0
322 && GLContext.GetGsContextChanged() == 0
323 && !UserRenderContextChanged
324 && !rendererChanged
325 && Geometry.MergeNew()) {
326 doReset = false;
327 } else {
328 // couldn't merge; draw the old geometry so we can reset and start a new block
329 if (Geometry.GetArrayType() == kLinear)
330 RendererManager.GetCurRenderer().DrawLinearArrays(Geometry);
331 else
332 RendererManager.GetCurRenderer().DrawIndexedArrays(Geometry);
333 }
334 }
335
336 if (doReset) {
337 Geometry.MakeNewValuesCurrent();
338 Geometry.ResetNew();
339
340 if (rendererChanged) {
341 RendererManager.MakeNewRendererCurrent();
342 RendererManager.LoadRenderer(GLContext.GetVif1Packet());
343 }
344 SyncRendererContext(Geometry.GetPrimType());
345 SyncGsContext();
346 }
347}
348
349void CImmGeomManager::PrimChanged(GLenum primType)
350{
351 GLContext.PrimChanged();
352 RendererManager.PrimChanged(primType);
353}
354
355void CImmGeomManager::SyncRenderer()
356{
357 if (RendererManager.UpdateNewRenderer()) {
358 RendererManager.MakeNewRendererCurrent();
359 RendererManager.LoadRenderer(GLContext.GetVif1Packet());
360 }
361}
362
363void CImmGeomManager::SyncRendererContext(GLenum primType)
364{
365 // resend the rendering context if necessary
366 if (GLContext.GetRendererContextChanged()
367 || (RendererManager.IsCurRendererCustom() && UserRenderContextChanged)) {
368 RendererManager.GetCurRenderer().InitContext(primType,
369 GLContext.GetRendererContextChanged(),
370 UserRenderContextChanged);
371
372 GLContext.SetRendererContextChanged(false);
373 UserRenderContextChanged = false;
374 Prim = primType;
375 }
376}
377
378void CImmGeomManager::SyncGsContext()
379{
380 if (tU32 changed = GLContext.GetGsContextChanged()) {
381 // has the texture changed?
382 bool texEnabled = GLContext.GetTexManager().GetTexEnabled();
383 CVifSCDmaPacket& packet = GLContext.GetVif1Packet();
384 if (texEnabled
385 && changed & GsCtxtFlags::Texture) {
386 // we have to wait for all previous buffers to finish, or
387 // the new texture settings might beat the geometry to the gs..
388 packet.Cnt();
389 packet.Flush().Nop();
390 packet.CloseTag();
391 GLContext.GetTexManager().UseCurTexture(GLContext.GetVif1Packet());
392 }
393
394 // has the draw environment changed?
395 if (changed & GsCtxtFlags::DrawEnv) {
396 // as with textures..
397 packet.Cnt();
398 packet.Flush().Nop();
399 packet.CloseTag();
400 // FIXME
401 GLContext.AddingDrawEnvToPacket((tU128*)GLContext.GetVif1Packet().GetNextPtr() + 1);
402 GLContext.GetImmDrawContext().GetDrawEnv().SendSettings(GLContext.GetVif1Packet());
403 }
404
405 GLContext.SetGsContextChanged(false);
406 }
407}
408
409void CImmGeomManager::SyncColorMaterial(bool pvColorsArePresent)
410{
411 CMaterialManager& mm = GLContext.GetMaterialManager();
412 if (pvColorsArePresent && mm.GetColorMaterialEnabled()) {
413 switch (mm.GetColorMaterialMode()) {
414 case GL_EMISSION:
415 mNotImplemented("Only GL_DIFFUSE can change per-vertex");
416 break;
417 case GL_AMBIENT:
418 mNotImplemented("Only GL_DIFFUSE can change per-vertex");
419 break;
420 case GL_DIFFUSE:
421 // fix later..
422 GLContext.PerVtxMaterialChanged();
423 RendererManager.PerVtxMaterialChanged(RendererProps::kDiffuse);
424 break;
425 case GL_AMBIENT_AND_DIFFUSE:
426 mNotImplemented("Only GL_DIFFUSE can change per-vertex");
427 break;
428 case GL_SPECULAR:
429 mNotImplemented("Only GL_DIFFUSE can change per-vertex");
430 // PerVtxMaterialChanged( PerVtxMaterial::kSpecular );
431 break;
432 }
433 } else {
434 RendererManager.PerVtxMaterialChanged(RendererProps::kNoMaterial);
435 }
436}
437
438void CImmGeomManager::Flush()
439{
440 if (Geometry.IsPending()) {
441 if (Geometry.GetArrayType() == kLinear)
442 RendererManager.GetCurRenderer().DrawLinearArrays(Geometry);
443 else
444 RendererManager.GetCurRenderer().DrawIndexedArrays(Geometry);
445 Geometry.Reset();
446 }
447}
virtual void InitContext(GLenum primType, tU32 rcChanges, bool userRcChanged)=0
virtual void DrawIndexedArrays(CGeometryBlock &block)
Draw arrays of vertices that are accessed by index (i.e., glDrawElements)
Definition renderer.h:130
virtual void DrawLinearArrays(CGeometryBlock &block)
Draw arrays of vertices that are accessed linearly (i.e., glDrawArrays)
Definition renderer.h:125