got rid of all occurences of the old and deleted Neuro_Print() and Debug_Print()...
[neuro.git] / src / video / coredraw.c
blob45ad5db2a0861d0c4311ed64bb4acb5415e8fb40
1 /*
2 * libneuro, a light weight abstraction of high or lower libraries
3 * and toolkit for applications.
4 * Copyright (C) 2005-2006 Nicholas Niro, Robert Lemay
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 /* coredraw.c
22 * the core drawing algorithm.
25 /*-------------------- Extern Headers Including --------------------*/
26 #include <string.h> /* memcpy */
28 /*-------------------- Local Headers Including ---------------------*/
29 #include <global.h>
30 #include <extlib.h> /* we mainly use the blitting function and screen updating functions */
31 #include <ebuf.h> /* we mainly use the single item cleaning function Neuro_SCleanEBuf */
33 /*-------------------- Main Module Header --------------------------*/
34 #include "video.h"
35 #include <graphics.h>
38 /*-------------------- Other ----------------------------*/
40 NEURO_MODULE_CHANNEL("video/coredraw");
42 /*-------------------- Global Variables ----------------------------*/
44 /*-------------------- Static Variables ----------------------------*/
46 /*-------------------- Static Prototypes ---------------------------*/
50 /*-------------------- Static Functions ----------------------------*/
52 /* a function to resolve a bug that made the volatile objects
53 * mysteriously disapear. It was because the last element of the
54 * Dynamic object was not refreshed so if an element was just
55 * before the Dynamic object, it just made it disapear :).
57 * This function searches the element just before the input element
58 * and returns it.
60 static INSTRUCTION_ENGINE *
61 get_Previous_Object_To_Object(INSTRUCTION_ENGINE *indep)
63 INSTRUCTION_ENGINE *cur, *last = NULL;
65 cur = Graphics_GetFirstElem();
67 if (cur == NULL)
68 return NULL;
70 if (indep == cur)
71 return NULL;
73 while (cur)
76 if (cur == indep)
78 /* Debug_Val(0, "found the previous elem 0x%x, (his next 0x%x)\n",
79 last, last->next);*/
80 return last;
84 last = cur;
85 cur = cur->next;
89 return NULL;
92 /* del_mask : 0 is don't clean any buffers (big memory leak)
93 * 1 is clean only the raw engine
94 * 2 is clean only the queue(instruction) engine
95 * 3 is clean both
97 static void
98 Core_clean_object(INSTRUCTION_ENGINE *cur, int dont_redraw_section, u8 del_mask)
100 Rectan buf;
101 INSTRUCTION_ENGINE *last = NULL;
102 EBUF *verify_m;
104 /* this functions needs to destroy an element
105 * from both the instruction buffer and the raw
106 * buffer.
108 * the first step we do is fill a special Rectan
109 * rectangle with the position and size of
110 * the image. Then, we draw this position and
111 * size black on screen. After that is done, we
112 * have to redraw previous objects (if theres any).
117 if (debug_track_fonts)
119 if (cur->current->layer >= 99999)
121 NEURO_TRACE("Destroying font", NULL);
122 Debug_Val(0, "&0x%x\n", cur);
126 /* Graphics_DebugQueueIntegrityCheck(); */
128 if (!cur)
129 return;
131 /* Debug_Val(0, "destroying element address 0x%x\n", cur); */
133 buf.x = cur->current->dx;
134 buf.y = cur->current->dy;
135 buf.w = cur->current->src.w;
136 buf.h = cur->current->src.h;
138 /*if (background)
139 Lib_BlitObject(background, &buf, sclScreen2, &buf);
140 else
141 Lib_FillRect(sclScreen2, &buf, 0);
144 if (dont_redraw_section == 0)
146 Lib_FillRect(Neuro_GetScreenBuffer(), &buf, 0);
148 Graphics_RedrawSection(cur);
151 if (debug_clean_instruction_buffer)
153 Neuro_CreateEBuf(&verify_m);
154 Graphics_DebugBufferQueue(verify_m);
157 if (debug_clean_instruction_buffer)
159 NEURO_TRACE("*initial values", NULL);
160 Debug_Val(0, "Amount of elems %d\n", Neuro_GiveEBufCount(verify_m) - 1);
161 Graphics_DebugPrintMissing(verify_m);
164 /* only set the previous element (last) if the element we need to
165 * destroy isn't the first one
167 if (cur != Graphics_GetFirstElem())
168 last = get_Previous_Object_To_Object(cur);
169 if (last)
171 /* Debug_Val(0, "changing last's(0x%x) next 0x%x to 0x%x\n", last,
172 last->next, cur->next);*/
174 last->next = cur->next;
177 /* check to see if the element cur is either first_element
178 * or last_element and if so, we will destituate it.
180 if (cur == Graphics_GetFirstElem())
182 Graphics_SetFirstElem(cur->next);
185 if (cur == Graphics_GetLastElem())
187 if (last)
189 last->next = NULL;
190 Graphics_SetLastElem(last);
192 else
193 Graphics_SetLastElem(NULL);
196 if (debug_clean_instruction_buffer)
198 NEURO_TRACE("*before real destroy", NULL);
199 Graphics_DebugPrintMissing(verify_m);
202 /*if (use_memory_pool)
203 Push_Data_To_Pool(POOL_QUEUE, cur);
204 else*/
206 /* INSTRUCTION_ENGINE *temp; */
209 temp = cur;
210 cur = cur->next;
213 /* Debug_Val(0, "before queue total %d\n",
214 Neuro_GiveEBufCount(_Queue) + 1);*/
216 if (del_mask == 1 || del_mask == 3)
217 Neuro_SCleanEBuf(Graphics_GetRawBuffer(), cur->current);
218 /* Debug_Val(0, "-- element address 0x%x destroyed\n", cur); */
219 if (del_mask == 2 || del_mask == 3)
220 Neuro_SCleanEBuf(Graphics_GetQueueBuffer(), cur);
222 /* Debug_Val(0, "after queue total %d\n",
223 Neuro_GiveEBufCount(_Queue) + 1); */
224 /* continue; */
227 if (debug_clean_instruction_buffer)
229 NEURO_TRACE("**After the destroy", NULL);
230 /*Debug_Val(0, "Amount of elems in verify %d in queue %d\n",
231 Neuro_GiveEBufCount(verify_m) - 1,
232 Neuro_GiveEBufCount(_Queue) - 1);*/
233 NEURO_TRACE("**Full output", NULL);
235 Graphics_DebugPrintQueue();
237 Graphics_DebugPrintMissing(verify_m);
238 Neuro_CleanEBuf(&verify_m);
241 /* Graphics_DebugQueueIntegrityCheck(); */
244 static void
245 clean_object(INSTRUCTION_ENGINE *cur, int dont_redraw_section)
247 Core_clean_object(cur, dont_redraw_section, 3);
250 /*-------------------- Global Functions ----------------------------*/
252 /* take note that we don't do any checks for valid pointers and such
253 * this function is supposed to be a backbone to an interface function
254 * which itself does the parity checks.
256 void
257 Graphics_DestroyElement(INSTRUCTION_ENGINE *elem)
259 RAW_ENGINE *tmp;
260 Rectan dst;
262 /* we destroy only the queue buffer because we want to make
263 * the emplacement of the element into a more comfortable
264 * place for the algorithm to avoid glitches.
267 tmp = elem->current;
269 /* we clean only the queue element and keep the raw engine buffer */
270 Core_clean_object(elem, 1, 2);
272 dst.x = tmp->dx;
273 dst.y = tmp->dy;
275 tmp->type = TDRAW_SDESTROY;
277 /* we put the raw buffer back into the queue */
278 Graphics_PushRaw(tmp);
281 void
282 Graphics_CoreDrawAll()
284 Rectan isrc, idst;
285 INSTRUCTION_ENGINE *cur, *last = NULL;
286 u32 safety = 10000; /* safety decrementor to avoid death loop */
288 if (Neuro_EBufIsEmpty(Graphics_GetQueueBuffer()))
289 return;
291 cur = Graphics_GetFirstElem();
293 /* start the real drawing */
294 while (cur)
297 if (safety <= 0)
299 NEURO_ERROR("To avoid a death loop, had to bail out of the instruction loop after 1000 loops", NULL);
300 break; /* safety break */
302 else
303 safety--;
305 if (check_integrity_on_draw)
307 NEURO_TRACE("Data integrity check before drawing", NULL);
308 Graphics_DebugQueueIntegrityCheck();
311 memcpy(&isrc, &cur->current->src, sizeof(Rectan));
313 idst.x = cur->current->dx;
314 idst.y = cur->current->dy;
316 if (debug_instruction_buffer)
317 Debug_Val(0, "%s Flushing type %d layer %d\n", __FUNCTION__, cur->current->type, cur->current->layer);
319 /* draw the surface_ptr to the screen buffer. */
320 switch (cur->current->type)
322 case TDRAW_STATIC:
325 /* Debug_Val(0, "static draw (%d,%d) %dx%d to (%d,%d)\n",
326 isrc.x, isrc.y, isrc.w, isrc.h,
327 idst.x, idst.y);
332 Lib_BlitObject(cur->current->surface_ptr, &isrc, Neuro_GetScreenBuffer(),
333 &idst);
335 cur->current->type = TDRAW_SDRAWN;
337 /* Graphics_RedrawSection(cur); */
339 /* Debug_Val(0, "drawn static\n"); */
341 if (debug_track_fonts)
343 if (cur->current->layer >= 99999)
345 NEURO_TRACE("Drawing font", NULL);
346 Debug_Val(0, "Coord (%d,%d) &0x%x\n",
347 cur->current->dx,
348 cur->current->dy, cur);
352 break;
354 case TDRAW_SDRAWN:
356 /* nothing needed for this type */
357 /* Debug_Val(0, "already drawn\n"); */
359 break;
361 case TDRAW_SREDRAW:
363 /* Debug_Val(0, "address of surface 0x%x\n", cur->current->surface_ptr); */
365 /* now we redraw the actual element */
366 Lib_BlitObject(cur->current->surface_ptr, &isrc, Neuro_GetScreenBuffer(),
367 &idst);
369 /* we cleanly redrawn the static element so we
370 * set the element's flag to drawn
372 cur->current->type = TDRAW_SDRAWN;
374 /* then we redraw the stuff that could have been
375 * there and actually need to be visible(and are above
376 * our element, ie layers).
378 * broken for some reason
380 Graphics_RedrawSection(cur);
382 /* Debug_Val(0, "Redrawn a static element\n"); */
384 break;
386 case TDRAW_SDESTROY:
388 INSTRUCTION_ENGINE *tmp;
390 if (cur->current->layer > 1000)
391 Debug_Print("Cleaned a static image");
394 tmp = cur;
396 cur = cur->next;
398 clean_object(tmp, 0);
400 /* we restart the loop completely since we need to draw
401 * the volatile types first before drawing the rest..
403 cur = Graphics_GetFirstElem();
405 if (cur)
406 continue;
408 break;
410 case TDRAW_DYNAMIC:
412 Lib_BlitObject(cur->current->surface_ptr, &isrc,
413 Neuro_GetScreenBuffer(), &idst);
415 cur->current->type = TDRAW_DYNAMIC_CLEAN;
417 if (dynamic_debug)
418 Debug_Val(0, "Dynamic : Tagging addr %x to clean\n", cur);
419 /* Debug_Val(0, "drawn dynamic\n"); */
421 break;
423 #if temp
424 case TDRAW_DYNAMIC_CLEAN:
426 /* Lib_BlitObject(cur->current->surface_ptr, &isrc,
427 sclScreen2, &idst);*/
429 /* clean_object(cur); */
431 break;
432 #endif /* temp */
434 case TDRAW_VOLATILE:
436 /*Debug_Val(0, "Volatile draw (%d,%d) %dx%d to (%d,%d) image 0x%x\n",
437 isrc.x, isrc.y, isrc.w, isrc.h,
438 idst.x, idst.y,
439 cur->current->surface_ptr);
442 Lib_BlitObject(cur->current->surface_ptr, &isrc,
443 Neuro_GetScreenBuffer(), &idst);
445 /* NOTE that we CAN't USE clean_object() BECAUSE
446 * it actually makes the image all BLACK
447 * so it nullifies the action of this COMPLETELY.
449 if (last)
450 last->next = cur->next;
452 /* check to see if the element cur is either first_element
453 * or last_element and if so, we will destituate it.
455 if (cur == Graphics_GetFirstElem())
457 Graphics_SetFirstElem(cur->next);
460 if (cur == Graphics_GetLastElem())
462 if (last)
464 last->next = NULL;
465 Graphics_SetLastElem(last);
470 /*if (use_memory_pool)
471 Push_Data_To_Pool(POOL_QUEUE, cur);
472 else*/
474 INSTRUCTION_ENGINE *temp;
476 temp = cur;
477 cur = cur->next;
479 Neuro_SCleanEBuf(Graphics_GetRawBuffer(), temp->current);
480 Neuro_SCleanEBuf(Graphics_GetQueueBuffer(), temp);
482 if (cur)
483 continue;
486 break;
489 default:
491 Debug_Val(0, "ERROR Draw unknown type %d\n", cur->current->type);
493 break;
496 if (cur)
498 last = cur;
499 if (cur->next == NULL && cur != Graphics_GetLastElem())
501 NEURO_ERROR("cur->next is NULL AND it isn't the last element, bad, very bad...", NULL);
503 cur = cur->next;
505 else
506 break;
510 Graphics_SetDrawnLastCycle();
511 /* Lib_FillRect(sclScreen, &test_BoundFix, 0); */
514 void
515 Graphics_SetAllToRedraw()
517 INSTRUCTION_ENGINE *cur;
519 cur = Graphics_GetFirstElem();
521 if (cur == NULL)
522 return;
524 while (cur)
526 if (cur->current->type == TDRAW_SDRAWN)
527 cur->current->type = TDRAW_STATIC; /* TDRAW_SREDRAW seems to do a flaw */
529 cur = cur->next;
532 if (debug_instruction_buffer)
533 NEURO_TRACE("Just Set all the instructions to be redrawn", NULL);
536 /* Graphics_CoreCleanAll might have cleaned objects
537 * that should be drawn so we will redraw those in this
538 * function.
539 * returns non zero if a volatile type was pushed
542 Graphics_RedrawSection(INSTRUCTION_ENGINE *indep)
544 Rectan buf, indep_body;
545 INSTRUCTION_ENGINE *cur;
546 int bounds_ret = 0;
547 int output = 0;
550 indep_body.x = indep->current->dx;
551 indep_body.y = indep->current->dy;
552 indep_body.w = indep->current->src.w;
553 indep_body.h = indep->current->src.h;
555 cur = Graphics_GetFirstElem();
557 if (cur == NULL)
558 return 0;
560 while (cur)
563 if (cur == indep)
565 cur = cur->next;
566 continue;
569 if (!cur->current)
571 Debug_Val(0, "BAD : the instruction 0x%x has an empty content!\n",
572 cur);
574 Debug_Val(0, "DEBUG data : indep 0x%x its next element 0x%x\n",
575 indep, indep->next);
576 /* odd error, this ain't supposed to happen :L */
577 return 0;
580 if (debug_track_fonts)
582 if (cur->current->layer >= 99999 && indep->current->layer >= 99999)
584 NEURO_TRACE("INITIAL Redrawing font", NULL);
586 Debug_Val(0, "Font type %d (%d,%d) &0x%x\n", cur->current->type,
587 buf.x, buf.y, cur);
591 if (cur->current->type == TDRAW_SDRAWN)
594 buf.x = cur->current->dx;
595 buf.y = cur->current->dy;
596 buf.w = cur->current->src.w;
597 buf.h = cur->current->src.h;
599 bounds_ret = Neuro_BoundsCheck(&indep_body, &buf);
600 /* bounds_ret = 2; */
602 if (debug_track_fonts)
604 if (cur->current->layer >= 99999 && indep->current->layer >= 99999)
606 NEURO_TRACE("INITIAL 2 Redrawing font", NULL);
607 Debug_Val(0, "bounds_ret %d current (%d,%d) indep (%d,%d)\n",
608 bounds_ret,
609 buf.x, buf.y,
610 indep_body.x, indep_body.y);
614 if (bounds_ret == 0)
616 Rectan bufa;
618 bufa.x = cur->current->dx;
619 bufa.y = cur->current->dy;
620 bufa.w = 0;
621 bufa.h = 0;
623 Neuro_PushVolatileDraw(cur->current->layer, &cur->current->src,
624 &bufa, cur->current->surface_ptr);
626 /*Debug_Val(0, "dynamic is inside this object\n");*/
628 if (debug_track_fonts)
630 if (cur->current->layer >= 99999)
631 NEURO_TRACE("Redrawing font #0", NULL);
634 output = 1;
637 if (bounds_ret == 2)
639 Rectan isrc, idst;
641 memcpy(&isrc, &cur->current->src, sizeof(Rectan));
643 idst.x = cur->current->dx;
644 idst.y = cur->current->dy;
645 idst.w = 0;
646 idst.h = 0;
648 Neuro_VerticalBoundCrop(&indep_body, &isrc, &idst);
649 Neuro_HorizontalBoundCrop(&indep_body, &isrc, &idst);
651 Neuro_PushVolatileDraw(cur->current->layer,
652 &isrc, &idst, cur->current->surface_ptr);
654 if (debug_track_fonts)
656 if (cur->current->layer >= 99999)
657 NEURO_TRACE("Redrawing font #2", NULL);
660 output = 1;
663 if (bounds_ret == 3)
665 Rectan isrc, idst, hack;
667 memcpy(&isrc, &cur->current->src, sizeof(Rectan));
669 idst.x = cur->current->dx;
670 idst.y = cur->current->dy;
671 idst.w = 0;
672 idst.h = 0;
675 if (indep_body.x > buf.x)
677 isrc.x += indep_body.x - buf.x;
678 idst.x += indep_body.x - buf.x;
680 /*isrc.y += buf.y - indep_body.y;
681 idst.y += buf.y - indep_body.y;*/
683 isrc.w -= buf.w - indep_body.w;
684 /* isrc.h += indep_body.h - buf.h; */
686 else
688 /*isrc.x += buf.x - indep_body.x;
689 idst.x += buf.x - indep_body.x;*/
691 isrc.y += indep_body.y - buf.y;
692 idst.y += indep_body.y - buf.y;
694 /* isrc.w += indep_body.w - buf.w; */
695 isrc.h -= buf.h - indep_body.h;
698 /* Neuro_PushVolatileDraw(cur->current->layer,
699 &isrc, &idst, cur->current->surface_ptr);*/
701 /* temporary hack that seems to work, we draw the whole
702 * static image... this needs testing and a better
703 * algorithm.
706 hack.x = cur->current->dx;
707 hack.y = cur->current->dy;
708 hack.w = 0;
709 hack.h = 0;
711 Neuro_PushVolatileDraw(cur->current->layer, &cur->current->src,
712 &hack, cur->current->surface_ptr);
714 /*Debug_Val(0, "we have a case 3 situation!\n");*/
716 if (debug_track_fonts)
718 if (cur->current->layer >= 99999)
719 NEURO_TRACE("Redrawing font #3", NULL);
722 output = 1;
725 /* indep is inside cur */
726 if (bounds_ret == 4)
728 Rectan bufa;
729 Rectan nsrc;
731 bufa.x = indep_body.x;
732 bufa.y = indep_body.y;
733 bufa.w = 0;
734 bufa.h = 0;
736 nsrc.x = indep_body.x - cur->current->dx;
737 nsrc.y = indep_body.y - cur->current->dy;
738 nsrc.w = indep_body.w;
739 nsrc.h = indep_body.h;
742 bufa.x = 0;
743 bufa.y = 0;
744 bufa.w = 0;
745 bufa.h = 0;
747 nsrc.x = 0;
748 nsrc.y = 0;
749 nsrc.w = cur->current->src.w;
750 nsrc.h = cur->current->src.h;
753 Neuro_PushVolatileDraw(cur->current->layer, &nsrc,
754 &bufa, cur->current->surface_ptr);
756 if (debug_track_fonts)
758 if (cur->current->layer >= 99999)
759 NEURO_TRACE("Redrawing font #4", NULL);
762 output = 1;
765 /* Debug_Val(0, "Redraw Section debug #%d\n", bounds_ret); */
767 cur = cur->next;
770 return output;
773 void
774 Graphics_CoreCleanAll()
776 INSTRUCTION_ENGINE *cur;
778 cur = Graphics_GetFirstElem();
780 if (cur == NULL)
781 return;
783 /* "reset" the emplacement of the last position of the image
784 * with the background if theres one or with the color black
785 * if none.
787 while (cur)
789 clean_object(cur, 1);
791 cur = cur->next;
794 Graphics_ResetScreenDraw();
797 /* only clean those with the type TDRAW_DYNAMIC_CLEAN */
798 void
799 Graphics_CoreCleanDoneDynamics()
801 INSTRUCTION_ENGINE *cur;
803 cur = Graphics_GetFirstElem();
805 if (cur == NULL)
806 return;
808 /* "reset" the emplacement of the last position of the image
809 * with the background if theres one or with the color black
810 * if none.
812 while (cur)
814 if (cur->current->type == TDRAW_DYNAMIC_CLEAN)
816 clean_object(cur, 0);
819 cur = cur->next;
823 void
824 Graphics_FreeVObject(v_object *source)
826 INSTRUCTION_ENGINE *cur, *tmp;
828 /* this function was made to avoid the painter's algorithm
829 * to have an element contain an image surface that was
830 * freed before it was processed resulting in a segmentation
831 * fault.
834 cur = Graphics_GetFirstElem();
836 while (cur)
838 tmp = cur->next;
840 if (cur->current->surface_ptr == source)
842 /*if (cur->current->type == TDRAW_SDRAWN)
843 Neuro_DestroyDraw(cur);
844 else*/
845 Core_clean_object(cur, 0, 3);
848 cur = tmp;
852 Lib_FreeVobject(source);