HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tiledevice.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  * Sample application showing how to use IMG_TileDevice by writing constant
27  * image planes (like $HH/public/deepmplay.C). IMG_TileDevice is the
28  * interface used by imdisplay and by mantra to write tiles to mplay and
29  * the IPR, so it is faster to use IMG_TileDevice directly rather than
30  * using imdisplay.
31  *
32  * To send images to the IPR, you can specify the port number using the -s
33  * option. This can be retrieved in soho by evaluating the
34  * vm_image_mplay_socketport property.
35  */
36 
37 
38 #include <UT/UT_Args.h>
39 #include <UT/UT_Exit.h>
40 #include <UT/UT_Main.h>
41 #include <UT/UT_WorkBuffer.h>
42 #include <IMG/IMG_TileDevice.h>
43 #include <IMG/IMG_TileOptions.h>
44 #include <TIL/TIL_TileMPlay.h>
45 
46 #define XRES 320 // Image X resolution
47 #define YRES 240 // Image Y resolution
48 #define TXRES 16 // Tile X resolution
49 #define TYRES 16 // Tile Y resolution
50 
51 struct PlaneDef {
52  const char *myName;
55 };
56 
58  { "C", IMG_UCHAR, IMG_RGBA }, // C plane is unsigned char, RGBA
59  { "s", IMG_FLOAT, IMG_1CHAN }, // s plane is float, single channel
60  { "Normal", IMG_FLOAT, IMG_RGB }, // N plane is float, RGB data
61 };
62 
63 #define NPLANES (sizeof(thePlanes)/sizeof(PlaneDef))
64 
65 static void *
66 buildTiles()
67 {
68  int pixels = TXRES * TYRES;
69  size_t bytes = 0;
70  for (int i = 0; i < NPLANES; i++)
71  {
72  int words = pixels * IMGvectorSize(thePlanes[i].myColorModel);
73  bytes += words * IMGbyteSize(thePlanes[i].myFormat);
74  }
75 
76  void *tdata = ::malloc(bytes);
77  char *ptr = (char *)tdata;
78  for (int i = 0; i < NPLANES; i++)
79  {
80  unsigned short *sdata;
81  unsigned char *cdata;
82  unsigned int *idata;
83  float *fdata;
84 
85  int words = pixels * IMGvectorSize(thePlanes[i].myColorModel);
86 
87  cdata = (unsigned char *)ptr;
88  sdata = (unsigned short *)ptr;
89  idata = (unsigned int *)ptr;
90  fdata = (float *)ptr;
91 
92  // Just fill in with some constant values.
93  for (int c = 0; c < words; c++)
94  {
95  switch (thePlanes[i].myFormat)
96  {
97  case IMG_UCHAR: *cdata++ = 0x85; break;
98  case IMG_USHORT: *sdata++ = 0x8512; break;
99  case IMG_UINT: *idata++ = 0x84123456; break;
100  default: *fdata++ = 0.763;
101  }
102  }
103 
104  ptr += words*IMGbyteSize(thePlanes[i].myFormat);
105  }
106 
107  return tdata;
108 }
109 
110 static void
111 splitHostPort(UT_String &host, UT_String &port, const char *hostname)
112 {
113  const char *colon = strchr(hostname, ':');
114  if (colon)
115  {
116  int len = colon - hostname;
117  host.harden(colon, len);
118  colon++; // Move past the colon
119  }
120  else
121  {
122  colon = hostname;
123  }
124  port.harden(colon);
125 }
126 
127 static void
128 sendPlaneDefinitions(IMG_TileDevice *dev,
129  const UT_String &host,
130  const UT_String &port)
131 {
132  IMG_TileOptionList flist;
133 
134  for (int i = 0; i < NPLANES; i++)
135  {
136  auto finfo = UTmakeUnique<IMG_TileOptions>();
137 
138  finfo->setPlaneInfo("ip", thePlanes[i].myName,
139  0, thePlanes[i].myFormat, thePlanes[i].myColorModel);
140 
141  // These format options allow sending tiles to an existing tile
142  // device (such as the IPR) rather than opening a new one. They
143  // only need to be set for plane 0 but it's harmless to send them
144  // for all planes.
145 
146  if (host) finfo->setFormatOption("sockethost", host);
147  if (port) finfo->setFormatOption("socketport", port);
148 
149  flist.append(std::move(finfo));
150  }
151 
152  if (!dev->openMulti(flist, XRES, YRES, TXRES, TYRES, 1.0))
153  {
154  ::fprintf(stderr, "Error opening tile device\n");
155  ::exit(1);
156  }
157 }
158 
159 static void
160 writeTile(IMG_TileDevice *dev, void *tdata, int tx0, int tx1, int ty0, int ty1)
161 {
162  if (!dev->writeTile(tdata, tx0, tx1, ty0, ty1))
163  {
164  ::fprintf(stderr, "Error writing data: %d %d %d %d\n",
165  tx0, tx1, ty0, ty1);
166  ::exit(1);
167  }
168  dev->flush();
169 }
170 
171 int
172 theMain(int argc, char *argv[])
173 {
174  UT_Args args;
175  UT_String host, port;
176 
177 #ifdef _WIN32
178  struct local {
179  static IMG_TileDevice *
180  creator(int middle)
181  {
182  return new TIL_TileMPlay(middle, 0);
183  }
184  };
185  IMG_TileDevice::setMPlayDevCreator(local::creator);
186 #endif
187 
188  args.initialize(argc, argv);
189  args.stripOptions("s:");
190 
191  if (args.found('s'))
192  splitHostPort(host, port, args.argp('s'));
193 
195 
196  sendPlaneDefinitions(dev, host, port);
197 
198  void *tdata = buildTiles();
199  for (int ty = 0; ty < YRES; ty += TYRES)
200  for (int tx = 0; tx < XRES; tx += TXRES)
201  ::writeTile(dev, tdata,
202  tx, SYSmin(tx+TXRES, XRES)-1,
203  ty, SYSmin(ty+TYRES, YRES)-1);
204 
205  free(tdata);
206 
207  return 0;
208 }
209 UT_MAIN(theMain);// exit with proper tear down
#define TXRES
Definition: tiledevice.C:48
static IMG_TileDevice * newDevice(const char *filename, const UT_Options *options=NULL)
int theMain(int argc, char *argv[])
Definition: tiledevice.C:172
virtual int openMulti(IMG_TileOptionList &flist, int xres, int yres, int tile_width, int tile_height, fpreal aspect)
void stripOptions(const char *options)
int found(int opt) const
Definition: UT_Args.h:61
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
Definition: glcorearb.h:108
#define XRES
Definition: tiledevice.C:46
static void setMPlayDevCreator(IMG_TileDevice *(*creator)(int))
IMG_DataType
Definition: IMG_FileTypes.h:17
PlaneDef thePlanes[]
Definition: tiledevice.C:57
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:215
#define YRES
Definition: tiledevice.C:47
auto fprintf(std::FILE *f, const S &fmt, const T &...args) -> int
Definition: printf.h:602
virtual int writeTile(const void *data, unsigned x0, unsigned x1, unsigned y0, unsigned y1)=0
UT_MAIN(theMain)
IMG_ColorModel
Definition: IMG_FileTypes.h:53
IMG_DataType myFormat
Definition: tiledevice.C:53
auto ptr(T p) -> const void *
Definition: format.h:2448
const char * myName
Definition: tiledevice.C:52
**If you just want to fire and args
Definition: thread.h:609
const char * argp(int opt, int which=0) const
Definition: UT_Args.h:66
virtual void flush()
void append(UT_UniquePtr< IMG_TileOptions > opt)
#define TYRES
Definition: tiledevice.C:49
void initialize(int argc, const char *const argv[])
IMG_ColorModel myColorModel
Definition: tiledevice.C:54
#define SYSmin(a, b)
Definition: SYS_Math.h:1539
#define NPLANES
Definition: tiledevice.C:63
Definition: format.h:2459