Rochelle O'Hagan (rohagan++at++viswiz.gmd.de)
Wed, 18 Nov 1998 18:32:38 +0100
The code follows:
Regards,
Rochelle O'Hagan
/*
* fpDivoService.c++
*
* use the DIVO board of IR
*
* Copyright (c) 1998 GMD
*
*
*/
/*
#ifdef PF20
#define PFTEX_RGB_8 PFTEX_RGB_5
#endif
*/
#include <libfp/fpBasic.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <Performer/pf.h>
#include <Performer/pfutil.h>
#include <Performer/pr.h>
#include <Performer/pr/pfTexture.h>
#include <Performer/pr/pfGeoSet.h>
// compile only on nessie
#ifdef COMPILE_ON_NESSIE
#include "fpDivoService.h"
#define PFNFY_DEBUG 1
#define CCIR_601_W 720
#define CCIR_601_H 576
#define SIR_W_RE2 768 // Sirius always transfers 768 pixels on
RE2
#define SIR_W_IR 720 // but 720 pixels on IR
#define SIR_H 576
// following are for PAL/625
// NTSC can use 1/2 H
//
#define TEX_W 1024
#define TEX_H_FRAME 1024
#define TEX_H_FIELD 512
DMbuffer _buff;
uint **dataPtr;
FP_BASE_DEFINE (fpDivoService)
fpDivoService::fpDivoService () :
_vTexType (fpDivoParam::VTEX_RGBA),
_divoState (fpDivoParam::FREE),
_divoSource (fpDivoParam::ANY_SOURCE),
_gfxType (fpDivoParam::GFX_OX_IR_DIVO)
{
FP_BASE_FINISH_CONSTRUCT ();
}
fpDivoService::~fpDivoService ()
{
}
void
fpDivoService::initClass ()
{
if (_classTypeId == fpType::badType ()) {
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::initClass");
FP_BASE_INIT (fpService, fpDivoService, TRUE, 0);
// int scheme functions
getClassTypeId ().registerMemberFunction ("init-divo", initDivoCB);
}
}
// ----
// setting DIVO Source according to given input
// ANY_SOURCE would do since there is only one DIGITAL_SOURCE
int fpDivoService::initDivo (fpString DivoString)
{
const char* tmpString = DivoString.c_str ();
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::initDivo: %s on
%d", tmpString, _gfxType);
_divoSource = fpDivoParam::ANY_SOURCE;
return 1;
}
#ifndef DONT_USE_GUILE
// ----
// scheme interface
SCM fpDivoService::initDivoCB (fpTyped* obj, SCM paramList)
{
SCM_ASSERT (scm_list_p (paramList) && scm_ilength (paramList) == 1,
paramList, SCM_WNA, "fpDivoService::initDivoCB");
fpString tmpString;
fp_gscm_unbundle (tmpString, gscm_car (paramList));
fpDivoService* self = (fpDivoService*) obj;
self->initDivo (tmpString);
return GSCM_UNSPECIFIED;
}
#else
Elk_Object fpDivoService::initDivoCB (fpTyped* obj, Elk_Object arg_list)
{
int num_args = Fast_Length(arg_list);
if (num_args != 1)
Primitive_Error("fpDivoService::initDivoCB(): wrong number of
arguments.");
fpString tmpString;
fp_scheme_unbundle (tmpString, P_Car(arg_list));
fpDivoService* self = (fpDivoService*) obj;
self->initDivo (tmpString);
return Elk_True;
}
#endif
// ----
// create texture and set parameter list
// for all divo boards
// by calling makeVideoTexture
pfTexture* fpDivoService::open (int divoNum)
{
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::open");
if ((_divoList[divoNum]._vlTexPath < 0) && _divoList[divoNum]._vTex) {
pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoService::open: divo
allready opened");
return _divoList[divoNum]._vTex;
}
// open divo board divoNum
int divoFlag = 1;
char* tmp;
tmp = (char *) glGetString(GL_RENDERER);
if (!strncmp(tmp,"IRL",3)) _gfxType=fpDivoParam::GFX_OX_IR_DIVO;
else _gfxType=fpDivoParam::GFX_O2_VIDEO;
// open path for DIVO divoNum
if (!_divoList[divoNum].open (divoNum, _vTexType, _divoSource,
_gfxType)) {
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::open: couldn't
open DIVO path");
divoFlag = 0;
return 0;
}
// start transfer and create texture
// only if divoboard is present
if (divoFlag) {
makeVideoTexture (divoNum);
return _divoList[divoNum]._vTex;
}
return 0;
}
// ----
// enable texture downloading
int fpDivoService::start (int divoNum)
{
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::start divoNum %d",
divoNum);
// start is called after opening in drawprocess
_divoState = fpDivoParam::PLAYING;
_divoList[divoNum].start();
return 1;
}
// ----
// disable texture downloading
int fpDivoService::stop (int divoNum)
{
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::stop divoNum %d",
divoNum);
_divoState = fpDivoParam::STOPED;
_divoList[divoNum].stop();
return 1;
}
// ----
// deallocate all resources
int fpDivoService::free (int divoNum)
{
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::free divoNum %d",
divoNum);
// pfDelete (_divoList[divoNum]._vTex);
// _divoList[divoNum]._vTex = NULL;
_divoState = fpDivoParam::FREE;
_divoList[divoNum].free();
return 1;
}
int fpDivoService::makeVideoTexture (int divoNum)
{
int numComponents;
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::makeVideoTexture");
if (_divoList[divoNum]._vTex != NULL)
return 0;
// create texture
_divoList[divoNum]._vTex = new (pfGetSharedArena ()) pfTexture;
// set parameters
_divoList[divoNum]._vTex->setName ("Video Texture");
int tvxsize, tvysize;
tvxsize = 1;
tvysize = 1;
while (tvxsize < _divoList[divoNum]._divFW) tvxsize <<= 1;
while (tvysize < _divoList[divoNum]._divFH * 1.0) tvysize <<= 1;
_divoList[divoNum]._vTex->setFilter (PFTEX_MINFILTER, PFTEX_LINEAR);
_divoList[divoNum]._vTex->setFilter (PFTEX_MAGFILTER, PFTEX_LINEAR);
_divoList[divoNum]._vTex->setFormat(PFTEX_SUBLOAD_FORMAT, PF_ON);
_divoList[divoNum]._vTex->setLoadOrigin (PFTEX_ORIGIN_DEST, 0, 0);
// tune for IR ??
switch (_vTexType) {
case fpDivoParam::VTEX_RGB:
_divoList[divoNum]._vTex->setFormat (PFTEX_INTERNAL_FORMAT,
PFTEX_RGB_8);
numComponents = 3;
break;
case fpDivoParam::VTEX_RGBA:
_divoList[divoNum]._vTex->setFormat
(PFTEX_INTERNAL_FORMAT,GL_RGBA8_EXT);
numComponents = 4;
break;
default:
pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoService::makeVideoTexture -
bad texture type");
pfDelete (_divoList[divoNum]._vTex);
_divoList[divoNum]._vTex = NULL;
return 0;
}
// capture fields, but not interlaced
//set size of texture
_divoList[divoNum]._vTex->setImage((uint *) NULL, 4, tvxsize, tvysize,
1);
_divoList[divoNum]._vTex->setLoadSize(_divoList[divoNum]._divFW,
_divoList[divoNum]._divFH);
_divoList[divoNum]._vTex->setFilter(PFTEX_EXTERNAL_FORMAT,
PFTEX_PACK_8);
_divoList[divoNum]._vTex->setLoadMode(PFTEX_LOAD_BASE,PFTEX_BASE_AUTO_SUBLOAD);
//
_divoList[divoNum]._vTex->setLoadMode(PFTEX_LOAD_BASE,PFTEX_BASE_APPLY);
_divoList[divoNum]._vTex->setLoadMode (PFTEX_LOAD_SOURCE,
PFTEX_SOURCE_VIDEO);
// _divoList[divoNum]._vTex->setLoadMode (PFTEX_LOAD_SOURCE,
PFTEX_SOURCE_IMAGE);
_divoList[divoNum]._vTex->setLoadMode (PFTEX_LOAD_SOURCE,
PFTEX_SOURCE_DMBUF);
return 1;
}
//
// ========================= Drawprocess only
===============================
// -- taken from the Sirius service but not really needed here, it can
be deleted!!
void fpDivoService::load (pfPipeWindow* pWin, int divoNum)
{
// don't do anything without pipe
if (pWin == 0) {
pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoService::load: no pipe
given");
return;
}
// look for currend state and stop or free divo if neccessary
if (_divoState == fpDivoParam::NO_DIVO) {
return;
}
VLEvent ev;
// will be printed out repeatedly
if (vlCheckEvent(_divoList[divoNum]._vlSrv,
VLSequenceLostMask|VLStreamPreemptedMask|
VLTransferCompleteMask|VLTransferFailedMask |
VLStreamStartedMask | VLStreamStoppedMask,
&ev) == -1) {
//pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoService::load: event
%d",ev.reason);
return;
}
pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoService::load: event
%d",ev.reason);
switch(ev.reason) {
case VLSequenceLost:
pfNotify(PFNFY_DEBUG,PFNFY_PRINT,"VLSequenceLost....\n");
break;
case VLTransferComplete:
pfNotify(PFNFY_DEBUG,PFNFY_PRINT,"VLTransferComplete....\n");
if(vlDMBufferGetValid(_divoList[divoNum]._vlSrv,
_divoList[divoNum]._vlTexPath, _divoList[divoNum]._drn, &_buff) == -1) {
pfNotify(PFNFY_DEBUG,PFNFY_PRINT,"vlDMBufferGetValid
failed....\n");
} else {
pfNotify(PFNFY_DEBUG,PFNFY_PRINT,"vlDMBufferGetValid
succeeded....\n");
*dataPtr = (uint *) dmBufferMapData(_buff);
int tvxsize, tvysize;
tvxsize = 1;
tvysize = 1;
while (tvxsize < _divoList[divoNum]._divFW) tvxsize <<= 1;
while (tvysize < _divoList[divoNum]._divFH * 1.0) tvysize <<= 1;
pfEnable(PFEN_TEXTURE);
pfTexture *tex = pfGetCurTex();
// _divoList[divoNum]._vTex->setImage((uint *) *dataPtr, 4,
tvxsize, tvysize, 1);
_divoList[divoNum]._vTex->apply();
_divoList[divoNum]._vTex->load();
dmBufferFree(_buff);
}
// pfEnable(PFEN_TEXTURE);
// _divoList[divoNum]._vTex->apply();
// _divoList[divoNum]._vTex->load();
break;
case VLTransferFailed:
pfNotify(PFNFY_DEBUG,PFNFY_PRINT,"VLTransfer FAILED ....\n");
break;
case VLStreamStarted:
pfNotify(PFNFY_DEBUG,PFNFY_PRINT,"VLStreamStarted....\n");
break;
case VLStreamPreempted:
cerr << "VLStreamPreempted!\n";
break;
case VLStreamBusy:
cerr << "VLStreamBusy!\n";
break;
case VLStreamAvailable:
cerr << "VLStreamAvailable!\n";
break;
default:
break;
}
// don't go further without texture
if (_divoList[divoNum]._vTex == 0) {
pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoService::load: no
texture");
return;
}
}
//
// ========================= fpDivoParam ===============================
// ----
// open a path from the divoboard of the given pipe to texture memory
int fpDivoParam::open (int divoNum, VideoTexType textureType, DivoSource
divoSource, GFXType gfxType)
{
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoParam::open: divo %d,
texType %d, source %d", divoNum, textureType, divoSource);
// if there is allready a path open, delete it
if (_currentState != FREE || _vlSrv) {
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoParam::open: DIVO path
allready open");
free ();
}
// ----
// depending on the given source, some parameters have to be set
_currentState = STOPED;
_currentSource = divoSource;
// ----
// setup video texture path
_deviceNo = divoNum;
_vlSrv = vlOpenVideo ("");
if (_vlSrv == NULL) {
pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoParam::open: cannot connect
to video server");
free ();
return 0;
}
_src = vlGetNode (_vlSrv, VL_SRC, VL_VIDEO, VL_ANY);
if (_src < 0) {
vlPerror ("vlGetNode Divo (video in)");
free ();
return 0;
}
_drn = vlGetNode (_vlSrv, VL_DRN, VL_MEM, VL_ANY);
if (_drn < 0) {
vlPerror ("vlGetNode Divo (memory)");
free ();
return 0;
}
_vlTexPath = vlCreatePath (_vlSrv, _deviceNo, _src, _drn);
if (_vlTexPath < 0) {
vlPerror ("vlCreatePath Divo (video texture)");
pfNotify(PFNFY_WARN, PFNFY_PRINT,"vlCreatePath Divo (video texture)
%d",_deviceNo);
free ();
return 0;
}
if (vlSetupPaths (_vlSrv, (VLPathList)&_vlTexPath, 1, VL_SHARE,
VL_SHARE) < 0) {
vlPerror ("vlSetupPaths Divo (video texture)");
free ();
return 0;
}
// ----
// Settings
int mask;
mask = VLStreamStartedMask | VLTransferCompleteMask |
VLTransferFailedMask | VLStreamStoppedMask | VLSequenceLostMask;
vlSelectEvents( _vlSrv, _vlTexPath, mask);
// packing
VLControlValue tex;
switch (textureType) {
case VTEX_RGB:
if (gfxType == fpDivoParam::GFX_OX_IR_DIVO) tex.intVal =
VL_PACKING_0444_8;
else tex.intVal = VL_PACKING_RGB_8;
break;
case VTEX_RGBA:
if (gfxType == GFX_OX_IR_DIVO) tex.intVal = VL_PACKING_4444_8;
else tex.intVal = VL_PACKING_ABGR_8;
break;
default:
pfNotify(PFNFY_WARN, PFNFY_PRINT, "fpDivoParam::open: - bad texture
type");
free ();
return 0;
}
if (vlSetControl (_vlSrv, _vlTexPath, _drn, VL_PACKING, &tex) < 0) {
vlPerror ("vlSetControl Divo: texture, packing");
free ();
return 0;
}
// colourspace
if (gfxType == fpDivoParam::GFX_OX_IR_DIVO) {
tex.intVal = VL_COLORSPACE_RGB;
if (vlSetControl (_vlSrv, _vlTexPath, _drn, VL_COLORSPACE, &tex) <0)
{
vlPerror ("vlSetControl Divo: texture, colorspace");
free();
return 0;
}
}
// capturing
VLControlValue capture;
capture.intVal = VL_CAPTURE_FIELDS;
if (vlSetControl (_vlSrv, _vlTexPath, _drn, VL_CAP_TYPE, &capture) <
0) {
vlPerror ("vlSetControl Divo: texture, capture");
free ();
return 0;
}
// get size of video-frame
VLControlValue size;
if (vlGetControl (_vlSrv, _vlTexPath, _src, VL_SIZE, &size) < 0) {
vlPerror ("vlGetControl Divo: video in, size");
free ();
return 0;
}
_divW = size.xyVal.x;
_divH = size.xyVal.y;
// get video-field size for texture which is based on field size
if (vlGetControl(_vlSrv, _vlTexPath, _drn, VL_SIZE, &size) < 0) {
vlPerror("vlGetControl: video field size for texture");
free();
return 0;
}
_divFW = size.xyVal.x;
_divFH = size.xyVal.y;
// int frameSize;
// frameSize=vlGetTransferSize(_vlSrv, _vlTexPath);
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoParam::open width %d; height
%d field width %d field height %d", _divW, _divH, _divFW, _divFH);
DMparams* plist;
if (dmParamsCreate(&plist)) {
vlPerror("Video::Start - dmParamsCreate failed!");
return 0;
}
else
printf("Divo *** dmParamsCreate successfull for O2 and ONYX2 ?!?
(WV)!\n");
int videoBufCt;
// dmBufferSetPoolDefaults(plist, 4, frameSize, DM_FALSE,
DM_FALSE);
dmBufferSetPoolDefaults(plist, 0, 0, DM_FALSE, DM_FALSE);
dmParamsSetInt(plist, DM_BUFFER_COUNT, 0);
vlDMGetParams(_vlSrv, _vlTexPath, _drn, plist);
videoBufCt = dmParamsGetInt(plist, DM_BUFFER_COUNT);
dmParamsSetInt(plist, DM_BUFFER_COUNT, videoBufCt + 1);
if (dmBufferCreatePool(plist, &_pool) != DM_SUCCESS) {
vlPerror("Video::Start Divo - dmBufferCreatePool failed '%s'\n");
}
dmParamsDestroy(plist);
if (!_pool) {
vlPerror("Divo no pool??");
return 0;
}
// Associate the pool with the path
if (vlDMPoolRegister(_vlSrv, _vlTexPath, _drn,_pool)) {
vlPerror("Divo no pool-path association");
dmBufferDestroyPool(_pool);
return 0;
}
VLControlValue timing, dominance;
//
// in 525 ("NTSC"), the odd field is drawn first (higher spacially).
// in 625 ("PAL"), the even field is drawn first
if (vlGetControl(_vlSrv, _vlTexPath, _src, VL_TIMING, &timing) <0) {
vlPerror("VlGetControl of timing");
return 0;
}
F1_is_first = (timing.intVal == VL_TIMING_625_CCIR601);
// check the FIELD_DOMINANCE only on nessie
// not on an O2
char* tmp;
tmp = (char *) glGetString(GL_RENDERER);
if (!strncmp(tmp,"IRL",3)) {
if (vlGetControl(_vlSrv, _vlTexPath, _src, VL_FIELD_DOMINANCE,
&dominance) <0) {
vlPerror("VlGetControl of dominance");
return 0;
}
}
F1_is_first ^= (dominance.intVal == VL_F2_IS_DOMINANT);
return 1;
}
// ----
// start playing
void fpDivoParam::start ()
{
// VLTransferDescriptor xferDesc;
int rc;
if (_currentState != STOPED)
return;
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoParam::start");
// if DIVO has not been opened yet or
// if it has been stopped and started again
// texture is already created but the path
// needs to be reopened
if (!_vlSrv) {
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoParam::start opening
DIVO");
char* tmp;
fpDivoParam::GFXType _gfxType;
tmp = (char *) glGetString(GL_RENDERER);
if (!strncmp(tmp,"IRL",3)) _gfxType=fpDivoParam::GFX_OX_IR_DIVO;
else _gfxType=fpDivoParam::GFX_O2_VIDEO;
// open path for DIVO divoNum
if (!open (_deviceNo, VTEX_RGBA, ANY_SOURCE, _gfxType)) {
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoService::start: couldn't
open DIVO path");
// divoFlag = 0;
return;
}
}
// link texture with the new or existing path
// _vTex->setLoadVal(PFTEX_LOAD_VIDEO_VLSERVER,(void *) _vlSrv);
// _vTex->setLoadVal(PFTEX_LOAD_VIDEO_VLPATH, (void *) _vlTexPath);
// _vTex->setLoadVal(PFTEX_LOAD_VIDEO_VLDRAIN, (void *) _drn);
// _vTex->setLoadVal(PFTEX_LOAD_DMBUF, (void *) _pool);
// begin transfer in both cases
_currentState = PLAYING;
rc = vlBeginTransfer(_vlSrv, _vlTexPath, 0, NULL);
if(rc < 0) {
vlPerror("Divo vlBeginTransfer");
return;
}
}
// ----
// stop playing
void fpDivoParam::stop ()
{
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoParam::stop");
if (_currentState != PLAYING)
return;
_currentState = STOPED;
vlEndTransfer (_vlSrv, _vlTexPath);
if (_pool) {
vlDMPoolDeregister(_vlSrv, _vlTexPath, _drn,_pool);
dmBufferDestroyPool(_pool);
}
vlDestroyPath(_vlSrv, _vlTexPath);
// free all resources except texture
if (_vlSrv)
vlCloseVideo (_vlSrv);
_vlSrv = 0;
_vlTexPath = 0;
_frame = 0;
_pool =0;
_currentSource = NO_SOURCE;
}
// ----
// free all resources
void fpDivoParam::free ()
{
pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "fpDivoParam::free divoNum %d",
_deviceNo);
if (_currentState == FREE)
return;
if (_vlSrv && _vlTexPath) {
vlEndTransfer (_vlSrv, _vlTexPath);
vlDestroyPath (_vlSrv, _vlTexPath);
}
if (_vlSrv)
vlCloseVideo (_vlSrv);
_vlSrv = 0;
_vlTexPath = 0;
_frame = 0;
_pool =0;
_currentState = FREE;
_currentSource = NO_SOURCE;
}
#endif
This archive was generated by hypermail 2.0b2 on Wed Nov 18 1998 - 09:33:38 PST