1 /*
2 Copyright (c) 2005-2021 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 /*
18 The original source for this example is
19 Copyright (c) 1994-2008 John E. Stone
20 All rights reserved.
21
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions
24 are met:
25 1. Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, this list of conditions and the following disclaimer in the
29 documentation and/or other materials provided with the distribution.
30 3. The name of the author may not be used to endorse or promote products
31 derived from this software without specific prior written permission.
32
33 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 SUCH DAMAGE.
44 */
45
46 #include <omp.h>
47 #include <string.h>
48
49 #include "machine.hpp"
50 #include "types.hpp"
51 #include "macros.hpp"
52 #include "vector.hpp"
53 #include "tgafile.hpp"
54 #include "trace.hpp"
55 #include "light.hpp"
56 #include "shade.hpp"
57 #include "camera.hpp"
58 #include "util.hpp"
59 #include "intersect.hpp"
60 #include "global.hpp"
61 #include "ui.hpp"
62 #include "tachyon_video.hpp"
63
64 // shared but read-only so could be private too
65 static thr_parms *all_parms;
66 static scenedef scene;
67 static int startx;
68 static int stopx;
69 static int starty;
70 static int stopy;
71 static flt jitterscale;
72 static int totaly, totalx;
73
74 static int grain_size = 50;
75 const int DIVFACTOR = 2;
76
77 #define MIN(a, b) ((a) < (b) ? (a) : (b))
78
render_one_pixel(int x,int y,unsigned int * local_mbox,unsigned int & serial,int startx,int stopx,int starty,int stopy)79 static color_t render_one_pixel(int x,
80 int y,
81 unsigned int *local_mbox,
82 unsigned int &serial,
83 int startx,
84 int stopx,
85 int starty,
86 int stopy) {
87 /* private vars moved inside loop */
88 ray primary, sample;
89 color col, avcol;
90 int R, G, B;
91 intersectstruct local_intersections;
92 int alias;
93 /* end private */
94
95 primary = camray(&scene, x, y);
96 primary.intstruct = &local_intersections;
97 primary.flags = RT_RAY_REGULAR;
98
99 serial++;
100 primary.serial = serial;
101 primary.mbox = local_mbox;
102 primary.maxdist = FHUGE;
103 primary.scene = &scene;
104 col = trace(&primary);
105
106 serial = primary.serial;
107
108 /* perform antialiasing if enabled.. */
109 if (scene.antialiasing > 0) {
110 for (alias = 0; alias < scene.antialiasing; alias++) {
111 serial++; /* increment serial number */
112 sample = primary; /* copy the regular primary ray to start with */
113 sample.serial = serial;
114
115 #pragma omp critical
116 {
117 sample.d.x += ((rand() % 100) - 50) / jitterscale;
118 sample.d.y += ((rand() % 100) - 50) / jitterscale;
119 sample.d.z += ((rand() % 100) - 50) / jitterscale;
120 }
121
122 avcol = trace(&sample);
123
124 serial = sample.serial; /* update our overall serial # */
125
126 col.r += avcol.r;
127 col.g += avcol.g;
128 col.b += avcol.b;
129 }
130
131 col.r /= (scene.antialiasing + 1.0);
132 col.g /= (scene.antialiasing + 1.0);
133 col.b /= (scene.antialiasing + 1.0);
134 }
135
136 /* Handle overexposure and underexposure here... */
137 R = (int)(col.r * 255);
138 if (R > 255)
139 R = 255;
140 else if (R < 0)
141 R = 0;
142
143 G = (int)(col.g * 255);
144 if (G > 255)
145 G = 255;
146 else if (G < 0)
147 G = 0;
148
149 B = (int)(col.b * 255);
150 if (B > 255)
151 B = 255;
152 else if (B < 0)
153 B = 0;
154
155 return video->get_color(R, G, B);
156 }
157
parallel_thread(patch * pchin,int depth)158 static void parallel_thread(patch *pchin, int depth) {
159 unsigned char col[3];
160 col[0] = col[1] = col[2] = (32 * depth) % 256;
161 depth++;
162 #pragma intel omp taskq firstprivate(depth)
163 {
164 int startx, stopx, starty, stopy;
165 int xs, ys;
166
167 startx = pchin->startx;
168 stopx = pchin->stopx;
169 starty = pchin->starty;
170 stopy = pchin->stopy;
171
172 if (((stopx - startx) >= grain_size) || ((stopy - starty) >= grain_size)) {
173 int xpatchsize = (stopx - startx) / DIVFACTOR + 1;
174 int ypatchsize = (stopy - starty) / DIVFACTOR + 1;
175 for (ys = starty; ys <= stopy; ys += ypatchsize)
176 for (xs = startx; xs <= stopx; xs += xpatchsize) {
177 patch pch;
178 pch.startx = xs;
179 pch.starty = ys;
180 pch.stopx = MIN(xs + xpatchsize, stopx);
181 pch.stopy = MIN(ys + ypatchsize, stopy);
182
183 #pragma intel omp task
184 parallel_thread(&pch, depth);
185 }
186 }
187 else {
188 /* just trace this patch */
189 unsigned int mboxsize = sizeof(unsigned int) * (max_objectid() + 20);
190 unsigned int *local_mbox = (unsigned int *)alloca(mboxsize);
191 memset(local_mbox, 0, mboxsize);
192
193 drawing_area drawing(startx, totaly - stopy, stopx - startx, stopy - starty);
194 for (int i = 1, y = starty; y < stopy; ++y, i++) {
195 if (!video->running)
196 continue;
197 drawing.set_pos(0, drawing.size_y - i);
198 unsigned int serial = 5 * ((stopx - startx) + (stopy - starty) * totalx);
199 for (int x = startx; x < stopx; x++) {
200 color_t c =
201 render_one_pixel(x, y, local_mbox, serial, startx, stopx, starty, stopy);
202 drawing.put_pixel(c);
203 }
204 }
205 video->next_frame();
206 }
207 }
208 }
209
thread_trace(thr_parms * parms)210 void *thread_trace(thr_parms *parms) {
211 // shared but read-only so could be private too
212 all_parms = parms;
213 scene = parms->scene;
214 startx = parms->startx;
215 stopx = parms->stopx;
216 starty = parms->starty;
217 stopy = parms->stopy;
218 jitterscale = 40.0 * (scene.hres + scene.vres);
219 totalx = parms->stopx - parms->startx + 1;
220 totaly = parms->scene.vres;
221
222 patch pch;
223 pch.startx = startx;
224 pch.stopx = stopx;
225 pch.starty = starty;
226 pch.stopy = stopy;
227 int g;
228 char *grain_str = getenv("TASKQ_GRAINSIZE");
229 if (grain_str && (sscanf(grain_str, "%d", &g) > 0) && (g > 0))
230 grain_size = g;
231 #pragma omp parallel
232 parallel_thread(&pch, 0);
233
234 return (nullptr);
235 }
236