1 /* 2 Copyright (c) 2005-2020 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 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 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 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